spaces->tabs

master
an 2019-07-05 23:21:11 -04:00
parent 8354207c75
commit e3eaeeec66
100 changed files with 8587 additions and 8590 deletions

View File

@ -5,34 +5,34 @@ err_bad_arg=1
err_bad_run=2
rm_if() {
if [[ -d $1 ]];
then
rm -rf "$1" && echo "removed dir $1"
elif [[ -f $1 ]]
then
rm -f "$1" && echo "removed file $1"
if [[ -d $1 ]];
then
rm -rf "$1" && echo "removed dir $1"
elif [[ -f $1 ]]
then
rm -f "$1" && echo "removed file $1"
fi
return 0
}
perish() {
rm_if "${tmpdir}"
exit "$1"
rm_if "${tmpdir}"
exit "$1"
}
err() {
echo "error, dropping build"
rm_if "${appdir}"
rm_if "${dmg}"
perish $1
echo "error, dropping build"
rm_if "${appdir}"
rm_if "${dmg}"
perish $1
}
:() {
echo "$@"
echo
eval "$@" || err ${err_bad_run}
echo "$@"
echo
eval "$@" || err ${err_bad_run}
}
declare -A icon_names=(
[Tycho]="resources/color/pfhor-hand.png"
[Tycho]="resources/color/pfhor-hand.png"
)
name=$1
@ -40,14 +40,14 @@ exe=$2
if [[ ! $name ]]
then
echo "program name needed (available: Tycho)"
err ${err_bad_arg}
echo "program name needed (available: Tycho)"
err ${err_bad_arg}
fi
if [[ ! $exe ]]
then
echo "full path to executable required (ex. '$0 $name ~/bin/maraiah-tycho')"
err ${err_bad_arg}
echo "full path to executable required (ex. '$0 $name ~/bin/maraiah-tycho')"
err ${err_bad_arg}
fi
app=${name}.app
@ -89,25 +89,25 @@ dmg=${exedir}/${name}.dmg
while IFS= read -r lnk
do
lnk=$(dirname "${lnk}")
: cp -r "${lnk}" "${appdir}/Contents/Frameworks"
lnk=$(dirname "${lnk}")
: cp -r "${lnk}" "${appdir}/Contents/Frameworks"
done < "${exedir}"/build/maraiah-tycho-*/out/etc/link.txt
echo "success: bundle written to ${appdir}"
if [[ ! "$NO_DMG" ]]
then
echo "creating the disk image..."
echo "creating the disk image..."
: rm_if "${dmg}"
: rm_if "${dmg}"
: mkdir -p "${diskdir}"
: cp -r "${appdir}" "${diskdir}"
: cp "${srcdir}/resources/Image.DS_Store" "${diskdir}/.DS_Store"
: ln -s /Applications "${diskdir}"
: hdiutil create -volname "${name}" -srcfolder "${diskdir}" "${dmg}"
: mkdir -p "${diskdir}"
: cp -r "${appdir}" "${diskdir}"
: cp "${srcdir}/resources/Image.DS_Store" "${diskdir}/.DS_Store"
: ln -s /Applications "${diskdir}"
: hdiutil create -volname "${name}" -srcfolder "${diskdir}" "${dmg}"
echo "success: dmg written to ${dmg}"
echo "success: dmg written to ${dmg}"
fi
perish ${err_ok}

View File

@ -6,158 +6,156 @@ use std::{collections::HashSet, fs, io, slice::from_ref};
/*
fn open(path: &str) -> ResultS<io::BufReader>
{
let fp = fs::File::open(path)?;
Ok(io::BufReader::new(fp))
let fp = fs::File::open(path)?;
Ok(io::BufReader::new(fp))
}
fn file_read<T, F>(path: &str, f: F) -> ResultS<T>
where F: FnOnce(&[u8]) -> ResultS<T>
where F: FnOnce(&[u8]) -> ResultS<T>
{
let mm = open(path)?;
let bp = &mm[machdr::try_mac_header(&mm)..];
let mm = open(path)?;
let bp = &mm[machdr::try_mac_header(&mm)..];
f(bp)
f(bp)
}
fn exists(path: String) -> Result<(), String>
{
match std::fs::metadata(path) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
match std::fs::metadata(path) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}
fn each_value<F>(opt: &clap::ArgMatches<'_>,
name: &str,
mut f: F)
-> ResultS<()>
where F: FnMut(&str) -> ResultS<()>
mut f: F) -> ResultS<()>
where F: FnMut(&str) -> ResultS<()>
{
if let Some(values) = opt.values_of(name) {
for value in values {
f(value)?;
}
}
if let Some(values) = opt.values_of(name) {
for value in values {
f(value)?;
}
}
Ok(())
Ok(())
}
fn dbg_info(data: impl std::fmt::Debug)
{
println!("{:#?}", data);
println!("{:#?}", data);
}
fn dump_map(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
{
let mut cnks = HashSet::new();
let mut cnks = HashSet::new();
if let Some(opt_cnks) = opt.values_of("chunks") {
for typ in opt_cnks {
cnks.insert(typ);
}
}
if let Some(opt_cnks) = opt.values_of("chunks") {
for typ in opt_cnks {
cnks.insert(typ);
}
}
Ok(())
Ok(())
}
fn dump_shp(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
{
unimplemented!();
unimplemented!();
}
fn dump_snd(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
{
unimplemented!();
unimplemented!();
}
fn sub_data_c(_opt: &clap::ArgMatches<'_>) -> ResultS<()>
{
unimplemented!();
unimplemented!();
}
fn sub_dump_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
{
each_value(opt, "map", |f| dump_map(opt, f))?;
each_value(opt, "shp", |f| dump_shp(opt, f))?;
each_value(opt, "snd", |f| dump_snd(opt, f))?;
each_value(opt, "map", |f| dump_map(opt, f))?;
each_value(opt, "shp", |f| dump_shp(opt, f))?;
each_value(opt, "snd", |f| dump_snd(opt, f))?;
Ok(())
Ok(())
}
fn sub_info_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
{
each_value(opt, "map", |f| Ok(dbg_info(file_read(f, map::read)?)))?;
each_value(opt, "shp", |f| Ok(dbg_info(file_read(f, shp::read)?)))?;
each_value(opt, "snd", |f| Ok(dbg_info(file_read(f, snd::read)?)))?;
each_value(opt, "map", |f| Ok(dbg_info(file_read(f, map::read)?)))?;
each_value(opt, "shp", |f| Ok(dbg_info(file_read(f, shp::read)?)))?;
each_value(opt, "snd", |f| Ok(dbg_info(file_read(f, snd::read)?)))?;
Ok(())
Ok(())
}
*/
fn main() -> ResultS<()>
{
use std::io::prelude::*;
use std::io::prelude::*;
let inp = include_bytes!("../tests/data/map/Test.in");
let mut rd = std::io::BufReader::new(&inp[..]);
let inp = include_bytes!("../tests/data/map/Test.in");
let mut rd = std::io::BufReader::new(&inp[..]);
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
let ed = map::data::read_all(mp.head(), &en).unwrap();
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
let ed = map::data::read_all(mp.head(), &en).unwrap();
write!(&mut std::fs::File::create("dicks.txt").unwrap(), "{:#?}", ed);
write!(&mut std::fs::File::create("dicks.txt").unwrap(), "{:#?}", ed);
/*
use clap::clap_app;
use clap::clap_app;
let sub_data = clap_app! {
@subcommand data =>
(about: "Dumps data into a discrete folder/YAML format")
};
let sub_data = clap_app! {
@subcommand data =>
(about: "Dumps data into a discrete folder/YAML format")
};
let sub_dump = clap_app! {
@subcommand dump =>
(about: "Dumps particular parts of data")
(@arg chunks: -c --chunks [name]... "Dumps named chunks from an entry")
(@group files =>
(@attributes +required +multiple)
(@arg map: -m --map [file]... {exists} "Loads Map files")
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
};
let sub_dump = clap_app! {
@subcommand dump =>
(about: "Dumps particular parts of data")
(@arg chunks: -c --chunks [name]... "Dumps named chunks from an entry")
(@group files =>
(@attributes +required +multiple)
(@arg map: -m --map [file]... {exists} "Loads Map files")
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
};
let sub_info = clap_app! {
@subcommand info =>
(about: "Outputs debug info")
(@group files =>
(@attributes +required +multiple)
(@arg map: -m --map [file]... {exists} "Loads Map files")
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
};
let sub_info = clap_app! {
@subcommand info =>
(about: "Outputs debug info")
(@group files =>
(@attributes +required +multiple)
(@arg map: -m --map [file]... {exists} "Loads Map files")
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
};
let opt = clap_app! {
(env!("CARGO_PKG_NAME")) =>
(version: maraiah::meta::version())
(author: maraiah::meta::authors().replace(':', ", "))
(about: maraiah::meta::description())
(setting: clap::AppSettings::SubcommandRequiredElseHelp)
(subcommand: sub_data)
(subcommand: sub_dump)
(subcommand: sub_info)
};
let opt = clap_app! {
(env!("CARGO_PKG_NAME")) =>
(version: maraiah::meta::version())
(author: maraiah::meta::authors().replace(':', ", "))
(about: maraiah::meta::description())
(setting: clap::AppSettings::SubcommandRequiredElseHelp)
(subcommand: sub_data)
(subcommand: sub_dump)
(subcommand: sub_info)
};
let opt = opt.get_matches();
let opt = opt.get_matches();
match opt.subcommand() {
("data", Some(opt)) => sub_data_c(opt)?,
("dump", Some(opt)) => sub_dump_c(opt)?,
("info", Some(opt)) => sub_info_c(opt)?,
_ => unreachable!(),
}
*/
match opt.subcommand() {
("data", Some(opt)) => sub_data_c(opt)?,
("dump", Some(opt)) => sub_dump_c(opt)?,
("info", Some(opt)) => sub_info_c(opt)?,
_ => unreachable!(),
}
*/
Ok(())
Ok(())
}
// EOF

View File

@ -6,136 +6,136 @@ use std::{convert::{TryFrom, TryInto}, fmt, num::NonZeroU16};
#[doc(hidden)]
#[macro_export]
macro_rules! rd_impl {
// worker, creates let statement for 16 bit numbers
(W $b:expr, $pth:path, $nam:ident, $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1]]);
};
// worker, creates let statement for 16 bit numbers
(W $b:expr, $pth:path, $nam:ident, $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1]]);
};
// worker, creates let statement for 32 bit numbers
(D $b:expr, $pth:path, $nam:ident, $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]);
};
// worker, creates let statement for 32 bit numbers
(D $b:expr, $pth:path, $nam:ident, $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]);
};
// big endian, u16
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
$crate::rd_impl!(W $b, u16::from_be_bytes, $nam, $n + $at);
};
// big endian, u16
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
$crate::rd_impl!(W $b, u16::from_be_bytes, $nam, $n + $at);
};
// big endian, i16
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
$crate::rd_impl!(W $b, i16::from_be_bytes, $nam, $n + $at);
};
// big endian, i16
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
$crate::rd_impl!(W $b, i16::from_be_bytes, $nam, $n + $at);
};
// big endian, u32
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
$crate::rd_impl!(D $b, u32::from_be_bytes, $nam, $n + $at);
};
// big endian, u32
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
$crate::rd_impl!(D $b, u32::from_be_bytes, $nam, $n + $at);
};
// big endian, i32
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
$crate::rd_impl!(D $b, i32::from_be_bytes, $nam, $n + $at);
};
// big endian, i32
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
$crate::rd_impl!(D $b, i32::from_be_bytes, $nam, $n + $at);
};
// little endian, u16
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
$crate::rd_impl!(W $b, u16::from_le_bytes, $nam, $n + $at);
};
// little endian, u16
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
$crate::rd_impl!(W $b, u16::from_le_bytes, $nam, $n + $at);
};
// little endian, i16
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
$crate::rd_impl!(W $b, i16::from_le_bytes, $nam, $n + $at);
};
// little endian, i16
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
$crate::rd_impl!(W $b, i16::from_le_bytes, $nam, $n + $at);
};
// little endian, u32
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
$crate::rd_impl!(D $b, u32::from_le_bytes, $nam, $n + $at);
};
// little endian, u32
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
$crate::rd_impl!(D $b, u32::from_le_bytes, $nam, $n + $at);
};
// little endian, i32
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
$crate::rd_impl!(D $b, i32::from_le_bytes, $nam, $n + $at);
};
// little endian, i32
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
$crate::rd_impl!(D $b, i32::from_le_bytes, $nam, $n + $at);
};
// either endianness, Angle
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Angle) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = $crate::fixed::Angle::from_bits($nam);
};
// either endianness, Angle
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Angle) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = $crate::fixed::Angle::from_bits($nam);
};
// either endianness, Fixed
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Fixed) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
let $nam = $crate::fixed::Fixed::from_bits($nam);
};
// either endianness, Fixed
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Fixed) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
let $nam = $crate::fixed::Fixed::from_bits($nam);
};
// either endianness, Unit
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Unit) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = $crate::fixed::Unit::from_bits($nam);
};
// either endianness, Unit
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Unit) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = $crate::fixed::Unit::from_bits($nam);
};
// either endianness, OptU16
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, OptU16) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = $crate::bin::OptU16::from($nam);
};
// either endianness, OptU16
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, OptU16) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = $crate::bin::OptU16::from($nam);
};
// either endianness, u16 -> usize
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u16) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = usize::from($nam);
};
// either endianness, u16 -> usize
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u16) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
let $nam = usize::from($nam);
};
// either endianness, u32 -> usize
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u32) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
let $nam = $crate::bin::usize_from_u32($nam);
};
// either endianness, u32 -> usize
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u32) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
let $nam = $crate::bin::usize_from_u32($nam);
};
// either endianness, enum type with TryFrom
($e:ident, $b:expr, $at:expr, $n:expr;
$nam:ident, enum, $et:ident$(::$etc:ident)*, $t:ident) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
let $nam: $et$(::$etc)* = std::convert::TryFrom::try_from($nam)?;
};
// either endianness, enum type with TryFrom
($e:ident, $b:expr, $at:expr, $n:expr;
$nam:ident, enum, $et:ident$(::$etc:ident)*, $t:ident) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
let $nam: $et$(::$etc)* = std::convert::TryFrom::try_from($nam)?;
};
// either endianness, bitflag type
($e:ident, $b:expr, $at:expr, $n:expr;
$nam:ident, flag, $ft:ident$(::$ftc:ident)*, $t:ident) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
let $nam = flag_ok!($ft$(::$ftc)*, $nam)?;
};
// either endianness, bitflag type
($e:ident, $b:expr, $at:expr, $n:expr;
$nam:ident, flag, $ft:ident$(::$ftc:ident)*, $t:ident) => {
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
let $nam = flag_ok!($ft$(::$ftc)*, $nam)?;
};
// no endianness, u8
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, u8) => {
let $nam = $b[$n + $at];
};
// no endianness, u8
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, u8) => {
let $nam = $b[$n + $at];
};
// no endianness, i8
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, i8) => {
let $nam = $b[$n + $at] as i8;
};
// no endianness, i8
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, i8) => {
let $nam = $b[$n + $at] as i8;
};
// no endianness, [u8]
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, u8) => {
let $nam = &$b[$n + $at..$n + $at + $rn];
};
// no endianness, [u8]
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, u8) => {
let $nam = &$b[$n + $at..$n + $at + $rn];
};
// no endianness, Ident
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Ident) => {
$crate::rd_impl!(D $b, Ident, $nam, $n + $at);
};
// no endianness, Ident
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Ident) => {
$crate::rd_impl!(D $b, Ident, $nam, $n + $at);
};
// no endianness, fn([u8]) -> T
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr;
$nam:ident, no_try, $f:expr) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn]);
};
// no endianness, fn([u8]) -> T
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr;
$nam:ident, no_try, $f:expr) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn]);
};
// no endianness, fn([u8]) -> Result<T>
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, $f:expr) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn])?;
};
// no endianness, fn([u8]) -> Result<T>
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, $f:expr) => {
let $nam = $f(&$b[$n + $at..$n + $at + $rn])?;
};
}
/// Reads structured data from a byte slice.
@ -201,12 +201,12 @@ macro_rules! rd_impl {
/// let buffer = &[4, 0, 2, 0, 0, 0, 6];
///
/// read_data! {
/// 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];
/// }
/// 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);
@ -218,16 +218,16 @@ macro_rules! rd_impl {
/// ```
#[macro_export]
macro_rules! read_data {
(
endian: $e:ident, buf: $b:expr, size: $sz:expr, start: $at:expr, data {
$(let $nam:ident = $t:ident$(::$tc:ident)*[$n:expr $(; $rn:expr)?]
$($ex:ident$(::$exc:ident)*)*;)*
}
) => {
$crate::bin::check_data($b, $at + $sz)?;
$($crate::rd_impl!($e, $b, $at, $n;
$($rn;)? $nam, $($ex$(::$exc)*,)* $t$(::$tc)*);)*
};
(
endian: $e:ident, buf: $b:expr, size: $sz:expr, start: $at:expr, data {
$(let $nam:ident = $t:ident$(::$tc:ident)*[$n:expr $(; $rn:expr)?]
$($ex:ident$(::$exc:ident)*)*;)*
}
) => {
$crate::bin::check_data($b, $at + $sz)?;
$($crate::rd_impl!($e, $b, $at, $n;
$($rn;)? $nam, $($ex$(::$exc)*,)* $t$(::$tc)*);)*
};
}
/// Checks if there is enough data in `b`.
@ -238,11 +238,11 @@ macro_rules! read_data {
#[inline]
pub fn check_data<T>(b: &[T], sz: usize) -> ResultS<()>
{
if b.len() < sz {
Err(err_msg("not enough data"))
} else {
Ok(())
}
if b.len() < sz {
Err(err_msg("not enough data"))
} else {
Ok(())
}
}
/// Casts a `u32` to a `usize`.
@ -262,7 +262,7 @@ pub fn check_data<T>(b: &[T], sz: usize) -> ResultS<()>
#[inline]
pub fn usize_from_u32(n: u32) -> usize
{
usize::try_from(n).expect("platform is 16-bit")
usize::try_from(n).expect("platform is 16-bit")
}
/// Creates an `Ident` from a slice.
@ -281,7 +281,7 @@ pub fn usize_from_u32(n: u32) -> usize
#[inline]
pub fn ident(b: &[u8]) -> Ident
{
Ident(b[0..4].try_into().expect("not enough data"))
Ident(b[0..4].try_into().expect("not enough data"))
}
/// Applies `u32::from_be_bytes` to a slice.
@ -300,7 +300,7 @@ pub fn ident(b: &[u8]) -> Ident
#[inline]
pub fn u32b(b: &[u8]) -> u32
{
u32::from_be_bytes(b[0..4].try_into().expect("not enough data"))
u32::from_be_bytes(b[0..4].try_into().expect("not enough data"))
}
/// Applies `u16::from_be_bytes` to a slice.
@ -319,7 +319,7 @@ pub fn u32b(b: &[u8]) -> u32
#[inline]
pub fn u16b(b: &[u8]) -> u16
{
u16::from_be_bytes(b[0..2].try_into().expect("not enough data"))
u16::from_be_bytes(b[0..2].try_into().expect("not enough data"))
}
/// Applies `i32::from_be_bytes` to a slice.
@ -338,7 +338,7 @@ pub fn u16b(b: &[u8]) -> u16
#[inline]
pub fn i32b(b: &[u8]) -> i32
{
i32::from_be_bytes(b[0..4].try_into().expect("not enough data"))
i32::from_be_bytes(b[0..4].try_into().expect("not enough data"))
}
/// Applies `i16::from_be_bytes` to a slice.
@ -357,7 +357,7 @@ pub fn i32b(b: &[u8]) -> i32
#[inline]
pub fn i16b(b: &[u8]) -> i16
{
i16::from_be_bytes(b[0..2].try_into().expect("not enough data"))
i16::from_be_bytes(b[0..2].try_into().expect("not enough data"))
}
/// Applies a read function over a slice.
@ -387,19 +387,19 @@ pub fn i16b(b: &[u8]) -> i16
/// assert_eq!(rd_array(inp, read_a_u16).unwrap(), vec![7_777u16, 777u16]);
/// ```
pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
where T: Sized,
F: Fn(&[u8]) -> ResultS<(T, usize)>
where T: Sized,
F: Fn(&[u8]) -> ResultS<(T, usize)>
{
let mut v = Vec::new();
let mut p = 0;
let mut v = Vec::new();
let mut p = 0;
while p < b.len() {
let (r, s) = read(&b[p..])?;
v.push(r);
p += s;
}
while p < b.len() {
let (r, s) = read(&b[p..])?;
v.push(r);
p += s;
}
Ok(v)
Ok(v)
}
/// Applies a read function a number of times over a slice.
@ -420,19 +420,19 @@ pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
pub fn rd_array_num<T, F>(b: &[u8],
n: usize,
read: F) -> ResultS<(Vec<T>, usize)>
where T: Sized,
F: Fn(&[u8]) -> ResultS<(T, usize)>
where T: Sized,
F: Fn(&[u8]) -> ResultS<(T, usize)>
{
let mut v = Vec::with_capacity(n);
let mut p = 0;
let mut v = Vec::with_capacity(n);
let mut p = 0;
for _ in 0..n {
let (r, s) = read(&b[p..])?;
v.push(r);
p += s;
}
for _ in 0..n {
let (r, s) = read(&b[p..])?;
v.push(r);
p += s;
}
Ok((v, p))
Ok((v, p))
}
/// Applies a read function over a slice with an offset table.
@ -454,150 +454,150 @@ pub fn rd_ofstable<T, F>(b: &[u8],
mut p: usize,
num: usize,
read: F) -> ResultS<Vec<T>>
where T: Sized,
F: Fn(&[u8]) -> ResultS<T>
where T: Sized,
F: Fn(&[u8]) -> ResultS<T>
{
let mut v = Vec::with_capacity(num);
let mut v = Vec::with_capacity(num);
for _ in 0..num {
let ofs = usize_from_u32(u32b(&b[p..p + 4]));
check_data(b, ofs)?;
v.push(read(&b[ofs..])?);
p += 4;
}
for _ in 0..num {
let ofs = usize_from_u32(u32b(&b[p..p + 4]));
check_data(b, ofs)?;
v.push(read(&b[ofs..])?);
p += 4;
}
Ok(v)
Ok(v)
}
impl From<u16> for OptU16
{
#[inline]
fn from(n: u16) -> Self
{
if n == u16::max_value() {
Self(None)
} else {
Self(NonZeroU16::new(n + 1))
}
}
#[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::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,
}
}
/// Returns the `u16` representation.
///
/// # Examples
///
/// ```
/// use maraiah::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`.
///
/// # Examples
///
/// ```
/// use maraiah::bin::OptU16;
///
/// assert_eq!(OptU16::none(), OptU16::from(u16::max_value()));
/// ```
#[inline]
pub const fn none() -> Self {Self(None)}
/// Creates an `OptU16` representing `None`.
///
/// # Examples
///
/// ```
/// use maraiah::bin::OptU16;
///
/// assert_eq!(OptU16::none(), OptU16::from(u16::max_value()));
/// ```
#[inline]
pub const fn none() -> Self {Self(None)}
/// Returns the `Option` representation.
///
/// # Examples
///
/// ```
/// use maraiah::bin::OptU16;
///
/// 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 {
None => None,
Some(n) => Some(n.get() - 1),
}
}
/// Returns the `Option` representation.
///
/// # Examples
///
/// ```
/// use maraiah::bin::OptU16;
///
/// 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 {
None => None,
Some(n) => Some(n.get() - 1),
}
}
/// Return the memory representation of this integer as a byte array
/// in big-endian (network) byte order.
#[inline]
pub fn to_be_bytes(self) -> [u8; 2]
{
<Self as Into<u16>>::into(self).to_be_bytes()
}
/// Return the memory representation of this integer as a byte array
/// in big-endian (network) byte order.
#[inline]
pub fn to_be_bytes(self) -> [u8; 2]
{
<Self as Into<u16>>::into(self).to_be_bytes()
}
/// Return the memory representation of this integer as a byte array
/// in little-endian byte order.
#[inline]
pub fn to_le_bytes(self) -> [u8; 2]
{
<Self as Into<u16>>::into(self).to_le_bytes()
}
/// Return the memory representation of this integer as a byte array
/// in little-endian byte order.
#[inline]
pub fn to_le_bytes(self) -> [u8; 2]
{
<Self as Into<u16>>::into(self).to_le_bytes()
}
}
impl fmt::Display for OptU16
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self.get() {
None => write!(f, "None"),
Some(n) => write!(f, "Some({})", n),
}
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self.get() {
None => write!(f, "None"),
Some(n) => write!(f, "Some({})", n),
}
}
}
impl fmt::Debug for OptU16
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self.get() {
None => write!(f, "OptU16::none()"),
Some(n) => write!(f, "OptU16::from({})", n),
}
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self.get() {
None => write!(f, "OptU16::none()"),
Some(n) => write!(f, "OptU16::from({})", n),
}
}
}
impl PartialEq<[u8; 4]> for Ident
{
#[inline]
fn eq(&self, o: &[u8; 4]) -> bool {self.0 == *o}
#[inline]
fn eq(&self, o: &[u8; 4]) -> bool {self.0 == *o}
}
impl<'a> PartialEq<[u8; 4]> for &'a Ident
{
#[inline]
fn eq(&self, o: &[u8; 4]) -> bool {PartialEq::eq(*self, o)}
#[inline]
fn eq(&self, o: &[u8; 4]) -> bool {PartialEq::eq(*self, o)}
}
impl<'a> PartialEq<&'a [u8; 4]> for Ident
{
#[inline]
fn eq(&self, o: &&'a [u8; 4]) -> bool {PartialEq::eq(self, *o)}
#[inline]
fn eq(&self, o: &&'a [u8; 4]) -> bool {PartialEq::eq(self, *o)}
}
/// A four-character-code identifier.

View File

@ -11,152 +11,152 @@ use crate::err::*;
/// `(cr_bit + width - 1) / 8` would overflow an index into `b`.
pub fn read_bits_b(b: &[u8], cr_bit: usize, width: u8) -> ResultS<u64>
{
if width == 0 {
return Ok(0);
}
if width == 0 {
return Ok(0);
}
if width > 64 {
bail!("invalid number of bits");
}
if width > 64 {
bail!("invalid number of bits");
}
let last = (cr_bit + usize::from(width) - 1) / 8;
let last = (cr_bit + usize::from(width) - 1) / 8;
if last >= b.len() {
bail!("not enough data");
}
if last >= b.len() {
bail!("not enough data");
}
let mut byte_ptr = cr_bit / 8;
let mut bits_ptr = cr_bit % 8;
let mut byte_ptr = cr_bit / 8;
let mut bits_ptr = cr_bit % 8;
let mut res = 0;
let mut res = 0;
for _ in 0..width {
res <<= 1;
for _ in 0..width {
res <<= 1;
if b[byte_ptr] & (1 << bits_ptr) != 0 {
res |= 1;
}
if b[byte_ptr] & (1 << bits_ptr) != 0 {
res |= 1;
}
bits_ptr += 1;
bits_ptr += 1;
if bits_ptr > 7 {
bits_ptr = 0;
byte_ptr += 1;
}
}
if bits_ptr > 7 {
bits_ptr = 0;
byte_ptr += 1;
}
}
Ok(res)
Ok(res)
}
/// The same as `read_bits_b`, but least-significant bit first.
pub fn read_bits_l(b: &[u8], cr_bit: usize, width: u8) -> ResultS<u64>
{
if width == 0 {
Ok(0)
} else {
let res = read_bits_b(b, cr_bit, width)?;
if width == 0 {
Ok(0)
} else {
let res = read_bits_b(b, cr_bit, width)?;
Ok(reverse_bits(res) >> (64 - width))
}
Ok(reverse_bits(res) >> (64 - width))
}
}
// FIXME: change this to u64::reverse_bits when stabilized
const fn reverse_bits(v: u64) -> u64
{
let v = v >> 1 & 0x5555_5555_5555_5555 | ((v & 0x5555_5555_5555_5555) << 1);
let v = v >> 2 & 0x3333_3333_3333_3333 | ((v & 0x3333_3333_3333_3333) << 2);
let v = v >> 4 & 0x0F0F_0F0F_0F0F_0F0F | ((v & 0x0F0F_0F0F_0F0F_0F0F) << 4);
v.swap_bytes()
let v = v >> 1 & 0x5555_5555_5555_5555 | ((v & 0x5555_5555_5555_5555) << 1);
let v = v >> 2 & 0x3333_3333_3333_3333 | ((v & 0x3333_3333_3333_3333) << 2);
let v = v >> 4 & 0x0F0F_0F0F_0F0F_0F0F | ((v & 0x0F0F_0F0F_0F0F_0F0F) << 4);
v.swap_bytes()
}
#[test]
fn bit_tests()
{
const INPUT: &[u8] = &[0b01100101, 0b10101010, 0b00010000, 0b00000000,
0b11111111, 0b11100001, 0b10101100, 0b00110011,
0b10100101, 0b11100000, 0b00000111, 0b00000001,
0b11001010, 0b10101111, 0b00101011, 0b01101010,
0b11010101, 0b10100011, 0b01010101, 0b11000001];
const INPUT: &[u8] = &[0b01100101, 0b10101010, 0b00010000, 0b00000000,
0b11111111, 0b11100001, 0b10101100, 0b00110011,
0b10100101, 0b11100000, 0b00000111, 0b00000001,
0b11001010, 0b10101111, 0b00101011, 0b01101010,
0b11010101, 0b10100011, 0b01010101, 0b11000001];
let mut p = 0;
let mut p = 0;
let n = read_bits_b(INPUT, p, 3).unwrap();
assert_eq!(n, 0b101);
p += 3;
let n = read_bits_b(INPUT, p, 3).unwrap();
assert_eq!(n, 0b101);
p += 3;
let n = read_bits_b(INPUT, p, 63).unwrap();
assert_eq!(n, 0b001100101010100001000000000001111111110000111001101011100110010);
p += 63;
let n = read_bits_b(INPUT, p, 63).unwrap();
assert_eq!(n, 0b001100101010100001000000000001111111110000111001101011100110010);
p += 63;
let n = read_bits_b(INPUT, p, 4).unwrap();
assert_eq!(n, 0b1001);
p += 4;
let n = read_bits_b(INPUT, p, 4).unwrap();
assert_eq!(n, 0b1001);
p += 4;
let n = read_bits_b(INPUT, p, 7).unwrap();
assert_eq!(n, 0b0100000);
p += 7;
let n = read_bits_b(INPUT, p, 7).unwrap();
assert_eq!(n, 0b0100000);
p += 7;
let n = read_bits_b(INPUT, p, 17).unwrap();
assert_eq!(n, 0b11111100000100000);
p += 17;
let n = read_bits_b(INPUT, p, 17).unwrap();
assert_eq!(n, 0b11111100000100000);
p += 17;
let n = read_bits_b(INPUT, p, 27).unwrap();
assert_eq!(n, 0b000101001111110101110101000);
p += 27;
let n = read_bits_b(INPUT, p, 27).unwrap();
assert_eq!(n, 0b000101001111110101110101000);
p += 27;
let n = read_bits_b(INPUT, p, 33).unwrap();
assert_eq!(n, 0b101011010101011110001011010101010);
p += 33;
let n = read_bits_b(INPUT, p, 33).unwrap();
assert_eq!(n, 0b101011010101011110001011010101010);
p += 33;
let n = read_bits_b(INPUT, p, 6).unwrap();
assert_eq!(n, 0b000011);
p += 6;
let n = read_bits_b(INPUT, p, 6).unwrap();
assert_eq!(n, 0b000011);
p += 6;
let e = read_bits_b(INPUT, p, 1);
assert!(if let Err(_) = e {true} else {false});
let e = read_bits_b(INPUT, p, 1);
assert!(if let Err(_) = e {true} else {false});
let e = read_bits_b(INPUT, p, 2);
assert!(if let Err(_) = e {true} else {false});
let e = read_bits_b(INPUT, p, 2);
assert!(if let Err(_) = e {true} else {false});
let mut p = 0;
let mut p = 0;
let n = read_bits_l(INPUT, 0, 3).unwrap();
assert_eq!(n, 0b101);
p += 3;
let n = read_bits_l(INPUT, 0, 3).unwrap();
assert_eq!(n, 0b101);
p += 3;
let n = read_bits_l(INPUT, p, 63).unwrap();
assert_eq!(n, 0b010011001110101100111000011111111100000000000100001010101001100);
p += 63;
let n = read_bits_l(INPUT, p, 63).unwrap();
assert_eq!(n, 0b010011001110101100111000011111111100000000000100001010101001100);
p += 63;
let n = read_bits_l(INPUT, p, 4).unwrap();
assert_eq!(n, 0b1001);
p += 4;
let n = read_bits_l(INPUT, p, 4).unwrap();
assert_eq!(n, 0b1001);
p += 4;
let n = read_bits_l(INPUT, p, 7).unwrap();
assert_eq!(n, 0b0000010);
p += 7;
let n = read_bits_l(INPUT, p, 7).unwrap();
assert_eq!(n, 0b0000010);
p += 7;
let n = read_bits_l(INPUT, p, 17).unwrap();
assert_eq!(n, 0b00000100000111111);
p += 17;
let n = read_bits_l(INPUT, p, 17).unwrap();
assert_eq!(n, 0b00000100000111111);
p += 17;
let n = read_bits_l(INPUT, p, 27).unwrap();
assert_eq!(n, 0b000101011101011111100101000);
p += 27;
let n = read_bits_l(INPUT, p, 27).unwrap();
assert_eq!(n, 0b000101011101011111100101000);
p += 27;
let n = read_bits_l(INPUT, p, 33).unwrap();
assert_eq!(n, 0b010101010110100011110101010110101);
p += 33;
let n = read_bits_l(INPUT, p, 33).unwrap();
assert_eq!(n, 0b010101010110100011110101010110101);
p += 33;
let n = read_bits_l(INPUT, p, 6).unwrap();
assert_eq!(n, 0b110000);
p += 6;
let n = read_bits_l(INPUT, p, 6).unwrap();
assert_eq!(n, 0b110000);
p += 6;
let e = read_bits_l(INPUT, p, 1);
assert!(if let Err(_) = e {true} else {false});
let e = read_bits_l(INPUT, p, 1);
assert!(if let Err(_) = e {true} else {false});
let e = read_bits_l(INPUT, p, 2);
assert!(if let Err(_) = e {true} else {false});
let e = read_bits_l(INPUT, p, 2);
assert!(if let Err(_) = e {true} else {false});
}
// EOF

View File

@ -4,85 +4,85 @@
#[macro_export]
macro_rules! c_bitfield
{
(
$(#[$outer:meta])*
pub struct $t:ident: $ti:ty {
$(
$(#[$inner:ident $($args:tt)*])*
$f:ident = $v:expr
),+
$(,)?
}
) => {
bitflags! {
$(#[$outer])*
pub struct $t: $ti {
$(
$(#[$inner $($args)*])*
const $f = 1 << $v;
)+
}
}
(
$(#[$outer:meta])*
pub struct $t:ident: $ti:ty {
$(
$(#[$inner:ident $($args:tt)*])*
$f:ident = $v:expr
),+
$(,)?
}
) => {
bitflags! {
$(#[$outer])*
pub struct $t: $ti {
$(
$(#[$inner $($args)*])*
const $f = 1 << $v;
)+
}
}
#[allow(unused_qualifications)]
impl std::str::FromStr for $t
{
type Err = $crate::err::ParseFlagError;
#[allow(unused_qualifications)]
impl std::str::FromStr for $t
{
type Err = $crate::err::ParseFlagError;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
let mut flags = Self::empty();
fn from_str(s: &str) -> Result<Self, Self::Err>
{
let mut flags = Self::empty();
for s in s.split('|') {
match s {
$(
stringify!($f) => flags.insert(Self::$f),
)+
"(none)" => (),
_ => return Err(Self::Err::new(stringify!($t)))
}
}
for s in s.split('|') {
match s {
$(
stringify!($f) => flags.insert(Self::$f),
)+
"(none)" => (),
_ => return Err(Self::Err::new(stringify!($t)))
}
}
Ok(flags)
}
}
}
Ok(flags)
}
}
}
}
#[cfg(test)]
mod test
{
use crate::err::ParseFlagError;
use std::str::FromStr;
use crate::err::ParseFlagError;
use std::str::FromStr;
c_bitfield! {
pub struct TestFlag: u16 {
ZERO = 0,
ONE = 1,
TWO = 2,
}
}
c_bitfield! {
pub struct TestFlag: u16 {
ZERO = 0,
ONE = 1,
TWO = 2,
}
}
#[test]
fn c_bitfield()
{
assert_eq!(TestFlag::from_bits(0), Some(TestFlag::empty()));
assert_eq!(TestFlag::from_bits(1), Some(TestFlag::ZERO));
assert_eq!(TestFlag::from_bits(2), Some(TestFlag::ONE));
assert_eq!(TestFlag::from_bits(4), Some(TestFlag::TWO));
assert_eq!(TestFlag::from_bits(8), None);
assert_eq!(TestFlag::from_str("(none)"), Ok(TestFlag::empty()));
assert_eq!(TestFlag::from_str("ZERO"), Ok(TestFlag::ZERO));
assert_eq!(TestFlag::from_str("ONE"), Ok(TestFlag::ONE));
assert_eq!(TestFlag::from_str("TWO"), Ok(TestFlag::TWO));
assert_eq!(TestFlag::from_str("ZERO|ONE|TWO"), Ok(TestFlag::all()));
assert_eq!(TestFlag::from_str("TWO|ZERO|ONE"), Ok(TestFlag::all()));
assert_eq!(TestFlag::from_str("ONE|ONE|ONE"), Ok(TestFlag::ONE));
assert_eq!(TestFlag::from_str("(none)|(none)"), Ok(TestFlag::empty()));
assert_eq!(TestFlag::from_str("(none)|ONE"), Ok(TestFlag::ONE));
assert_eq!(TestFlag::from_str("THREE"),
Err(ParseFlagError::new("TestFlag")));
}
#[test]
fn c_bitfield()
{
assert_eq!(TestFlag::from_bits(0), Some(TestFlag::empty()));
assert_eq!(TestFlag::from_bits(1), Some(TestFlag::ZERO));
assert_eq!(TestFlag::from_bits(2), Some(TestFlag::ONE));
assert_eq!(TestFlag::from_bits(4), Some(TestFlag::TWO));
assert_eq!(TestFlag::from_bits(8), None);
assert_eq!(TestFlag::from_str("(none)"), Ok(TestFlag::empty()));
assert_eq!(TestFlag::from_str("ZERO"), Ok(TestFlag::ZERO));
assert_eq!(TestFlag::from_str("ONE"), Ok(TestFlag::ONE));
assert_eq!(TestFlag::from_str("TWO"), Ok(TestFlag::TWO));
assert_eq!(TestFlag::from_str("ZERO|ONE|TWO"), Ok(TestFlag::all()));
assert_eq!(TestFlag::from_str("TWO|ZERO|ONE"), Ok(TestFlag::all()));
assert_eq!(TestFlag::from_str("ONE|ONE|ONE"), Ok(TestFlag::ONE));
assert_eq!(TestFlag::from_str("(none)|(none)"), Ok(TestFlag::empty()));
assert_eq!(TestFlag::from_str("(none)|ONE"), Ok(TestFlag::ONE));
assert_eq!(TestFlag::from_str("THREE"),
Err(ParseFlagError::new("TestFlag")));
}
}
// EOF

View File

@ -16,11 +16,11 @@
/// use std::convert::TryFrom;
///
/// c_enum! {
/// enum MyEnum: u16 {
/// Zero = 0,
/// One = 1,
/// Two = 2
/// }
/// enum MyEnum: u16 {
/// Zero = 0,
/// One = 1,
/// Two = 2
/// }
/// }
///
/// assert_eq!(MyEnum::try_from(0), Ok(MyEnum::Zero));
@ -33,88 +33,88 @@
#[macro_export]
macro_rules! c_enum
{
(
$(#[$outer:meta])*
$vi:vis enum $t:ident: $ti:ident {
$(
$(#[$inner:meta])*
$en:ident = $va:expr
),+
$(,)?
}
) => {
$(#[$outer])*
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr($ti)]
$vi enum $t {
$(
$(#[$inner])*
$en = $va,
)+
}
(
$(#[$outer:meta])*
$vi:vis enum $t:ident: $ti:ident {
$(
$(#[$inner:meta])*
$en:ident = $va:expr
),+
$(,)?
}
) => {
$(#[$outer])*
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr($ti)]
$vi enum $t {
$(
$(#[$inner])*
$en = $va,
)+
}
#[allow(unused_qualifications)]
impl std::convert::TryFrom<$ti> for $t
{
type Error = $crate::err::ReprError;
#[allow(unused_qualifications)]
impl std::convert::TryFrom<$ti> for $t
{
type Error = $crate::err::ReprError;
/// Returns, if representable, the variant of `Self` from `n`.
fn try_from(n: $ti) -> Result<Self, Self::Error>
{
match n {
$($va => Ok($t::$en),)+
n => Err(Self::Error::new(stringify!($t), n))
}
}
}
/// Returns, if representable, the variant of `Self` from `n`.
fn try_from(n: $ti) -> Result<Self, Self::Error>
{
match n {
$($va => Ok($t::$en),)+
n => Err(Self::Error::new(stringify!($t), n))
}
}
}
#[allow(unused_qualifications)]
impl std::str::FromStr for $t
{
type Err = $crate::err::ParseEnumError;
#[allow(unused_qualifications)]
impl std::str::FromStr for $t
{
type Err = $crate::err::ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
match s {
$(
stringify!($en) => Ok($t::$en),
)+
_ => Err(Self::Err::new(stringify!($t)))
}
}
}
};
fn from_str(s: &str) -> Result<Self, Self::Err>
{
match s {
$(
stringify!($en) => Ok($t::$en),
)+
_ => Err(Self::Err::new(stringify!($t)))
}
}
}
};
}
#[cfg(test)]
mod test
{
use crate::err::{ParseEnumError, ReprError};
use std::{convert::TryFrom, str::FromStr};
use crate::err::{ParseEnumError, ReprError};
use std::{convert::TryFrom, str::FromStr};
c_enum! {
enum TestEnum: u16 {
Zero = 0,
One = 1,
Two = 2,
}
}
c_enum! {
enum TestEnum: u16 {
Zero = 0,
One = 1,
Two = 2,
}
}
#[test]
fn c_enum()
{
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("TestEnum", 3)));
assert_eq!(TestEnum::try_from(4), Err(ReprError::new("TestEnum", 4)));
assert_eq!(TestEnum::try_from(5), Err(ReprError::new("TestEnum", 5)));
assert_eq!(TestEnum::from_str("Zero"), Ok(TestEnum::Zero));
assert_eq!(TestEnum::from_str("One"), Ok(TestEnum::One));
assert_eq!(TestEnum::from_str("Two"), Ok(TestEnum::Two));
assert_eq!(TestEnum::from_str("Three"),
Err(ParseEnumError::new("TestEnum")));
}
#[test]
fn c_enum()
{
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("TestEnum", 3)));
assert_eq!(TestEnum::try_from(4), Err(ReprError::new("TestEnum", 4)));
assert_eq!(TestEnum::try_from(5), Err(ReprError::new("TestEnum", 5)));
assert_eq!(TestEnum::from_str("Zero"), Ok(TestEnum::Zero));
assert_eq!(TestEnum::from_str("One"), Ok(TestEnum::One));
assert_eq!(TestEnum::from_str("Two"), Ok(TestEnum::Two));
assert_eq!(TestEnum::from_str("Three"),
Err(ParseEnumError::new("TestEnum")));
}
}
// EOF

View File

@ -3,22 +3,22 @@
// Accumulator for CRC function.
fn crc_accum(a: u32, _: u32) -> u32
{
if a & 1 == 1 {
ISO_3309_POLYNOMIAL ^ a >> 1
} else {
a >> 1
}
if a & 1 == 1 {
ISO_3309_POLYNOMIAL ^ a >> 1
} else {
a >> 1
}
}
// Initializes a CRC array.
// FIXME: use const fn when stabilized
fn crc_init() -> [u32; 256]
{
let mut t = [0; 256];
for (n, v) in t.iter_mut().enumerate() {
*v = (0..8).fold(n as u32, crc_accum);
}
t
let mut t = [0; 256];
for (n, v) in t.iter_mut().enumerate() {
*v = (0..8).fold(n as u32, crc_accum);
}
t
}
/// Creates an ADLER32 of all bytes in `b`.
@ -32,16 +32,16 @@ fn crc_init() -> [u32; 256]
/// ```
pub fn adler32(b: &[u8]) -> u32
{
let mut x = 1;
let mut y = 0;
let mut x = 1;
let mut y = 0;
for &z in b {
let z = u32::from(z);
x = (x + z) % ADLER32_MODULO;
y = (y + x) % ADLER32_MODULO;
}
for &z in b {
let z = u32::from(z);
x = (x + z) % ADLER32_MODULO;
y = (y + x) % ADLER32_MODULO;
}
(y << 16) | x
(y << 16) | x
}
/// Creates a CRC-32 of all bytes in `b` with the starting sum `s`. The
@ -56,8 +56,8 @@ pub fn adler32(b: &[u8]) -> u32
/// ```
pub fn crc32(b: &[u8], s: u32) -> u32
{
let t = crc_init();
!b.iter().fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)])
let t = crc_init();
!b.iter().fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)])
}
const ISO_3309_POLYNOMIAL: u32 = 0xEDB8_8320;

View File

@ -6,209 +6,209 @@ use std::cmp::Ordering;
/// Loads a ZLIB file header.
pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
{
const CM: u8 = 0b0000_1111;
const CINFO: u8 = 0b1111_0000;
const FDICT: u8 = 0b0010_0000;
const CM: u8 = 0b0000_1111;
const CINFO: u8 = 0b1111_0000;
const FDICT: u8 = 0b0010_0000;
read_data! {
endian: BIG, buf: b, size: 2, start: 0, data {
let fcheck = u16[0];
let cmf = u8[0];
let flg = u8[1];
}
}
read_data! {
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;
let cinfo = cmf & CINFO;
let cm = cmf & CM;
let cinfo = cmf & CINFO;
if cm != 8 {
bail!("unknown compression method");
}
if cm != 8 {
bail!("unknown compression method");
}
if cinfo > 7 << 4 {
bail!("lz77 window size logarithm is invalid");
}
if cinfo > 7 << 4 {
bail!("lz77 window size logarithm is invalid");
}
if fcheck % 31 != 0 {
bail!("invalid fcheck");
}
if fcheck % 31 != 0 {
bail!("invalid fcheck");
}
if flg & FDICT != 0 {
bail!("dictionary not supported");
}
if flg & FDICT != 0 {
bail!("dictionary not supported");
}
Ok(2)
Ok(2)
}
/// Loads a GZIP file header.
pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
{
const FHCRC: u8 = 1 << 1;
const FEXTRA: u8 = 1 << 2;
const FNAME: u8 = 1 << 3;
const FCOMMENT: u8 = 1 << 4;
const FRESERVED: u8 = 0xe0;
const FHCRC: u8 = 1 << 1;
const FEXTRA: u8 = 1 << 2;
const FNAME: u8 = 1 << 3;
const FCOMMENT: u8 = 1 << 4;
const FRESERVED: u8 = 0xe0;
read_data! {
endian: LITTLE, buf: b, size: 10, start: 0, data {
let id = u16[0];
let cm = u8[2];
let fl = u8[3];
}
}
read_data! {
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 {
bail!("not gzip format");
}
if id != 0x8b1f || cm != 8 {
bail!("not gzip format");
}
let mut p = 10;
let mut p = 10;
if fl & FRESERVED != 0 {
bail!("reserved flags set");
}
if fl & FRESERVED != 0 {
bail!("reserved flags set");
}
if fl & FEXTRA != 0 {
read_data! {
endian: LITTLE, buf: b, size: 2, start: p, data {
let xlen = u16[0] usize;
}
}
if fl & FEXTRA != 0 {
read_data! {
endian: LITTLE, buf: b, size: 2, start: p, data {
let xlen = u16[0] usize;
}
}
p += 2 + xlen;
p += 2 + xlen;
check_data(b, p)?;
}
check_data(b, p)?;
}
if fl & FNAME != 0 {
p += skip_zero_terminated_item(&b[p..])?;
}
if fl & FNAME != 0 {
p += skip_zero_terminated_item(&b[p..])?;
}
if fl & FCOMMENT != 0 {
p += skip_zero_terminated_item(&b[p..])?;
}
if fl & FCOMMENT != 0 {
p += skip_zero_terminated_item(&b[p..])?;
}
if fl & FHCRC != 0 {
p += 2;
if fl & FHCRC != 0 {
p += 2;
check_data(b, p)?;
}
check_data(b, p)?;
}
Ok(p)
Ok(p)
}
fn skip_zero_terminated_item(b: &[u8]) -> ResultS<usize>
{
if let Some(i) = b.iter().position(|&n| n == 0) {
Ok(i + 1)
} else {
bail!("no end of zero terminated item");
}
if let Some(i) = b.iter().position(|&n| n == 0) {
Ok(i + 1)
} else {
bail!("no end of zero terminated item");
}
}
/// Decompresses a DEFLATE compressed bitstream.
pub fn load_deflate(b: &[u8]) -> ResultS<(usize, Vec<u8>)>
{
let mut v = Vec::new();
let mut p = 0;
let mut v = Vec::new();
let mut p = 0;
loop {
let bfinal = read_bits_l(b, p, 1)?;
p += 1;
let btype = read_bits_l(b, p, 2)?;
p += 2;
loop {
let bfinal = read_bits_l(b, p, 1)?;
p += 1;
let btype = read_bits_l(b, p, 2)?;
p += 2;
match btype {
0b10 => p = stream_dynamic(&mut v, b, p)?,
0b01 => p = stream_s_table(&mut v, b, p)?,
0b00 => p = stream_literal(&mut v, b, p)?,
_ => bail!("bad btype"),
}
match btype {
0b10 => p = stream_dynamic(&mut v, b, p)?,
0b01 => p = stream_s_table(&mut v, b, p)?,
0b00 => p = stream_literal(&mut v, b, p)?,
_ => bail!("bad btype"),
}
if bfinal == 1 {
return Ok((p / 8, v));
}
}
if bfinal == 1 {
return Ok((p / 8, v));
}
}
}
fn stream_dynamic(v: &mut Vec<u8>, b: &[u8], mut p: usize) -> ResultS<usize>
{
const CODE_ORDERING: [usize; 19] =
[16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
const CODE_ORDERING: [usize; 19] =
[16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
// read header (number of literal alphabet codes, number of distance
// alphabet codes, and number of lengths for decoding the alphabet)
let hlit = read_bits_l(b, p, 5)?;
p += 5;
let hdist = read_bits_l(b, p, 5)?;
p += 5;
let hclen = read_bits_l(b, p, 4)?;
p += 4;
// read header (number of literal alphabet codes, number of distance
// alphabet codes, and number of lengths for decoding the alphabet)
let hlit = read_bits_l(b, p, 5)?;
p += 5;
let hdist = read_bits_l(b, p, 5)?;
p += 5;
let hclen = read_bits_l(b, p, 4)?;
p += 4;
let hlit = 257 + hlit as usize;
let hdist = 1 + hdist as usize;
let hclen = 4 + hclen as usize;
let hlit = 257 + hlit as usize;
let hdist = 1 + hdist as usize;
let hclen = 4 + hclen as usize;
// first, get the huffman coding for the alphabet (which is also compressed)
let mut code_table = [0; 19];
// first, get the huffman coding for the alphabet (which is also compressed)
let mut code_table = [0; 19];
for i in 0..hclen {
let len = read_bits_l(b, p, 3)? as u16;
p += 3;
for i in 0..hclen {
let len = read_bits_l(b, p, 3)? as u16;
p += 3;
code_table[CODE_ORDERING[i]] = len;
}
code_table[CODE_ORDERING[i]] = len;
}
// then, we decode the alphabet (doing both types at the same time, because
// they're encoded the same anyways)
let code_table = HuffmanTable::new(&code_table)?;
let mut alphabet = vec![0; hlit + hdist];
// then, we decode the alphabet (doing both types at the same time, because
// they're encoded the same anyways)
let code_table = HuffmanTable::new(&code_table)?;
let mut alphabet = vec![0; hlit + hdist];
p = read_alphabet(b, p, &mut alphabet, code_table)?;
p = read_alphabet(b, p, &mut alphabet, code_table)?;
if alphabet[256] == 0 {
bail!("no way to end block");
}
if alphabet[256] == 0 {
bail!("no way to end block");
}
// build the length and distance tables from this information
let table_len = HuffmanTable::new(&alphabet[0..hlit])?;
let table_dst = HuffmanTable::new(&alphabet[hlit..hlit + hdist])?;
// build the length and distance tables from this information
let table_len = HuffmanTable::new(&alphabet[0..hlit])?;
let table_dst = HuffmanTable::new(&alphabet[hlit..hlit + hdist])?;
output_tables(v, b, p, table_len, table_dst)
output_tables(v, b, p, table_len, table_dst)
}
#[allow(clippy::needless_range_loop)]
fn stream_s_table(v: &mut Vec<u8>, b: &[u8], p: usize) -> ResultS<usize>
{
let mut len = [0; 288];
let mut len = [0; 288];
for i in 0..144 {len[i] = 8;}
for i in 144..256 {len[i] = 9;}
for i in 256..280 {len[i] = 7;}
for i in 280..288 {len[i] = 8;}
for i in 0..144 {len[i] = 8;}
for i in 144..256 {len[i] = 9;}
for i in 256..280 {len[i] = 7;}
for i in 280..288 {len[i] = 8;}
let dst = [5; 30];
let dst = [5; 30];
let table_len = HuffmanTable::new(&len)?;
let table_dst = HuffmanTable::new(&dst)?;
let table_len = HuffmanTable::new(&len)?;
let table_dst = HuffmanTable::new(&dst)?;
output_tables(v, b, p, table_len, table_dst)
output_tables(v, b, p, table_len, table_dst)
}
fn stream_literal(v: &mut Vec<u8>, b: &[u8], p: usize) -> ResultS<usize>
{
// copy data directly from byte boundary
let mut p = p / 8 + 1;
// copy data directly from byte boundary
let mut p = p / 8 + 1;
read_data! {
endian: LITTLE, buf: b, size: 4, start: p, data {
let len = u16[0] usize;
}
}
read_data! {
endian: LITTLE, buf: b, size: 4, start: p, data {
let len = u16[0] usize;
}
}
p += 4;
v.extend(ok!(b.get(p..p + len), "not enough data")?);
p += 4;
v.extend(ok!(b.get(p..p + len), "not enough data")?);
Ok((p + len) * 8)
Ok((p + len) * 8)
}
fn read_alphabet(b: &[u8],
@ -216,63 +216,63 @@ fn read_alphabet(b: &[u8],
alphabet: &mut [u16],
code_table: HuffmanTable) -> ResultS<usize>
{
let mut i = 0;
while i < alphabet.len() {
let (bits, sym) = code_table.decode(b, p)?;
p += bits;
let mut i = 0;
while i < alphabet.len() {
let (bits, sym) = code_table.decode(b, p)?;
p += bits;
match sym {
0..=15 => {
// raw code
alphabet[i] = sym;
i += 1;
}
16 => {
// copy previous code 3-6 times
if i == 0 {
bail!("cannot copy on first alphabet code");
}
match sym {
0..=15 => {
// raw code
alphabet[i] = sym;
i += 1;
}
16 => {
// copy previous code 3-6 times
if i == 0 {
bail!("cannot copy on first alphabet code");
}
let len = usize::from(read_bits_l(b, p, 2)? as u8 + 3);
let lst = alphabet[i - 1];
p += 2;
let len = usize::from(read_bits_l(b, p, 2)? as u8 + 3);
let lst = alphabet[i - 1];
p += 2;
for _ in 0..len {
alphabet[i] = lst;
i += 1;
}
}
17 => {
// repeat '0' 3-10 times
let len = usize::from(read_bits_l(b, p, 3)? as u8 + 3);
p += 3;
for _ in 0..len {
alphabet[i] = lst;
i += 1;
}
}
17 => {
// repeat '0' 3-10 times
let len = usize::from(read_bits_l(b, p, 3)? as u8 + 3);
p += 3;
for _ in 0..len {
alphabet[i] = 0;
i += 1;
}
}
18 => {
// repeat '0' 11-138 times
let len = usize::from(read_bits_l(b, p, 7)? as u8 + 11);
p += 7;
for _ in 0..len {
alphabet[i] = 0;
i += 1;
}
}
18 => {
// repeat '0' 11-138 times
let len = usize::from(read_bits_l(b, p, 7)? as u8 + 11);
p += 7;
for _ in 0..len {
alphabet[i] = 0;
i += 1;
}
}
_ => {
bail!("bad symbol in alphabet");
}
}
for _ in 0..len {
alphabet[i] = 0;
i += 1;
}
}
_ => {
bail!("bad symbol in alphabet");
}
}
if i > alphabet.len() {
bail!("too many codes");
}
}
if i > alphabet.len() {
bail!("too many codes");
}
}
Ok(p)
Ok(p)
}
fn output_tables(v: &mut Vec<u8>,
@ -281,145 +281,145 @@ fn output_tables(v: &mut Vec<u8>,
table_len: HuffmanTable,
table_dst: HuffmanTable) -> ResultS<usize>
{
const LEN_BASE: [usize; 29] = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19,
23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
131, 163, 195, 227, 258];
const LEN_BASE: [usize; 29] = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19,
23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
131, 163, 195, 227, 258];
const LEN_EXTRA_BITS: [u8; 29] = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
0];
const LEN_EXTRA_BITS: [u8; 29] = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
0];
const DST_BASE: [usize; 30] = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65,
97, 129, 193, 257, 385, 513, 769, 1025,
1537, 2049, 3073, 4097, 0x1801, 0x2001,
0x3001, 0x4001, 0x6001];
const DST_BASE: [usize; 30] = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65,
97, 129, 193, 257, 385, 513, 769, 1025,
1537, 2049, 3073, 4097, 0x1801, 0x2001,
0x3001, 0x4001, 0x6001];
const DST_EXTRA_BITS: [u8; 30] = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13];
const DST_EXTRA_BITS: [u8; 30] = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13];
loop {
let (bits, sym) = table_len.decode(b, p)?;
p += bits;
loop {
let (bits, sym) = table_len.decode(b, p)?;
p += bits;
match sym.cmp(&256) {
Ordering::Less => {
// direct byte
v.push(sym as u8);
}
Ordering::Equal => {
return Ok(p);
}
Ordering::Greater => {
// this is a <len, dst> pair
let sym = sym - 257;
match sym.cmp(&256) {
Ordering::Less => {
// direct byte
v.push(sym as u8);
}
Ordering::Equal => {
return Ok(p);
}
Ordering::Greater => {
// this is a <len, dst> pair
let sym = sym - 257;
if sym > 29 {
bail!("invalid fixed code");
}
if sym > 29 {
bail!("invalid fixed code");
}
let sym = usize::from(sym);
let sym = usize::from(sym);
// first get the actual length and any extra bits it may have
let bits = LEN_EXTRA_BITS[sym];
let leng = LEN_BASE[sym] + read_bits_l(b, p, bits)? as usize;
p += usize::from(bits);
// first get the actual length and any extra bits it may have
let bits = LEN_EXTRA_BITS[sym];
let leng = LEN_BASE[sym] + read_bits_l(b, p, bits)? as usize;
p += usize::from(bits);
// decode the distance with its alphabet
let (bits, sym) = table_dst.decode(b, p)?;
p += bits;
// decode the distance with its alphabet
let (bits, sym) = table_dst.decode(b, p)?;
p += bits;
let sym = usize::from(sym);
let sym = usize::from(sym);
// get the actual distance and any extra bits it may have
let bits = DST_EXTRA_BITS[sym];
let dist = DST_BASE[sym] + read_bits_l(b, p, bits)? as usize;
p += usize::from(bits);
// get the actual distance and any extra bits it may have
let bits = DST_EXTRA_BITS[sym];
let dist = DST_BASE[sym] + read_bits_l(b, p, bits)? as usize;
p += usize::from(bits);
if dist > v.len() {
bail!("bad distance");
}
if dist > v.len() {
bail!("bad distance");
}
// copy bytes from earlier
for _ in 0..leng {
v.push(v[v.len() - dist]);
}
}
}
}
// copy bytes from earlier
for _ in 0..leng {
v.push(v[v.len() - dist]);
}
}
}
}
}
impl HuffmanTable
{
fn new(table: &[u16]) -> ResultS<Self>
{
let mut syms = vec![0; table.len()];
let mut nums = [0; 16];
fn new(table: &[u16]) -> ResultS<Self>
{
let mut syms = vec![0; table.len()];
let mut nums = [0; 16];
// count the number of symbols for each bit length
for &length in table {
nums[usize::from(length)] += 1;
}
// count the number of symbols for each bit length
for &length in table {
nums[usize::from(length)] += 1;
}
if usize::from(nums[0]) == table.len() {
bail!("bad table lengths");
}
if usize::from(nums[0]) == table.len() {
bail!("bad table lengths");
}
// make offsets into the symbol table for each bit count
let mut ofs = [0; 16];
// make offsets into the symbol table for each bit count
let mut ofs = [0; 16];
for i in 1..=14 {
ofs[i + 1] = ofs[i] + usize::from(nums[i]);
}
for i in 1..=14 {
ofs[i + 1] = ofs[i] + usize::from(nums[i]);
}
// make the actual bit pattern table
for (n, &length) in table.iter().enumerate() {
// length 0 means this code isn't used, so only try to make bit
// patterns for codes that actually exist
if length != 0 {
// make sure to make each offset unique
let offset = &mut ofs[usize::from(length)];
syms[*offset] = n as u16;
*offset += 1;
}
}
// make the actual bit pattern table
for (n, &length) in table.iter().enumerate() {
// length 0 means this code isn't used, so only try to make bit
// patterns for codes that actually exist
if length != 0 {
// make sure to make each offset unique
let offset = &mut ofs[usize::from(length)];
syms[*offset] = n as u16;
*offset += 1;
}
}
Ok(Self{nums, syms})
}
Ok(Self{nums, syms})
}
fn decode(&self, b: &[u8], mut p: usize) -> ResultS<(usize, u16)>
{
let mut code = 0_u16;
let mut first = 0_u16;
let mut index = 0_u16;
fn decode(&self, b: &[u8], mut p: usize) -> ResultS<(usize, u16)>
{
let mut code = 0_u16;
let mut first = 0_u16;
let mut index = 0_u16;
for i in 1..=15 {
// add bit from file
code |= read_bits_l(b, p, 1)? as u16;
p += 1;
for i in 1..=15 {
// add bit from file
code |= read_bits_l(b, p, 1)? as u16;
p += 1;
// check our symbol table for this one (quick tree check)
let count = self.nums[i];
// check our symbol table for this one (quick tree check)
let count = self.nums[i];
if i32::from(code) - i32::from(count) < i32::from(first) {
return Ok((i, self.syms[usize::from(index + code - first)]));
}
if i32::from(code) - i32::from(count) < i32::from(first) {
return Ok((i, self.syms[usize::from(index + code - first)]));
}
// continue on, trying to find the correct sequence
index += count;
first += count;
// continue on, trying to find the correct sequence
index += count;
first += count;
first <<= 1;
code <<= 1;
}
first <<= 1;
code <<= 1;
}
Err(ReprError::new("DEFLATE code", code).into())
}
Err(ReprError::new("DEFLATE code", code).into())
}
}
struct HuffmanTable {
nums: [u16; 16],
syms: Vec<u16>,
nums: [u16; 16],
syms: Vec<u16>,
}
// EOF

View File

@ -8,15 +8,15 @@
/// use maraiah::doc_comment;
///
/// doc_comment! {
/// concat!("Have a nice", " day", "!"),
/// const A: u32 = 5;
/// concat!("Have a nice", " day", "!"),
/// const A: u32 = 5;
/// }
///
/// assert_eq!(A, 5);
/// ```
#[macro_export]
macro_rules! doc_comment {
($x:expr, $($tt:tt)*) => {#[doc = $x] $($tt)*}
($x:expr, $($tt:tt)*) => {#[doc = $x] $($tt)*}
}
// EOF

View File

@ -5,40 +5,40 @@ pub use failure::{Error, Fail};
use std::fmt;
macro_rules! ok {
($v:expr, $msg:expr) => {
match $v {
Some(v) => Ok(v),
None => Err($crate::err::err_msg($msg)),
}
};
($v:expr, $msg:expr) => {
match $v {
Some(v) => Ok(v),
None => Err($crate::err::err_msg($msg)),
}
};
}
macro_rules! flag_ok {
($t:ident$(::$tc:ident)*, $v:expr) => {
{
let v = $v;
($t:ident$(::$tc:ident)*, $v:expr) => {
{
let v = $v;
match $t$(::$tc)*::from_bits(v) {
Some(v) => Ok(v),
None => Err($crate::err::ReprError::new(stringify!($t), v)),
}
}
};
match $t$(::$tc)*::from_bits(v) {
Some(v) => Ok(v),
None => Err($crate::err::ReprError::new(stringify!($t), v)),
}
}
};
}
macro_rules! bail {
($e:expr) => {
return Err($crate::err::err_msg($e));
};
($e:expr) => {
return Err($crate::err::err_msg($e));
};
}
#[macro_export]
macro_rules! backtrace {
($e:expr) => {
if cfg!(debug_assertions) {
dbg!($e.backtrace());
}
}
($e:expr) => {
if cfg!(debug_assertions) {
dbg!($e.backtrace());
}
}
}
/// Returns an `Error` with a static string.
@ -55,58 +55,58 @@ pub fn err_msg(msg: &'static str) -> Error {ErrMsg(msg).into()}
impl ParseEnumError
{
/// Returns an `Error` with a message for enumeration parsing errata.
///
/// # Examples
///
/// ```
/// use maraiah::err::ParseEnumError;
///
/// assert_eq!(format!("{}", ParseEnumError::new("TypeName")),
/// "could not parse TypeName");
/// ```
#[inline]
pub const fn new(t: &'static str) -> Self
{
Self(t)
}
/// Returns an `Error` with a message for enumeration parsing errata.
///
/// # Examples
///
/// ```
/// use maraiah::err::ParseEnumError;
///
/// assert_eq!(format!("{}", ParseEnumError::new("TypeName")),
/// "could not parse TypeName");
/// ```
#[inline]
pub const fn new(t: &'static str) -> Self
{
Self(t)
}
}
impl ParseFlagError
{
/// Returns an `Error` with a message for flag parsing errata.
///
/// # Examples
///
/// ```
/// use maraiah::err::ParseFlagError;
///
/// assert_eq!(format!("{}", ParseFlagError::new("TypeName")),
/// "could not parse TypeName");
/// ```
#[inline]
pub const fn new(t: &'static str) -> Self
{
Self(t)
}
/// Returns an `Error` with a message for flag parsing errata.
///
/// # Examples
///
/// ```
/// use maraiah::err::ParseFlagError;
///
/// assert_eq!(format!("{}", ParseFlagError::new("TypeName")),
/// "could not parse TypeName");
/// ```
#[inline]
pub const fn new(t: &'static str) -> Self
{
Self(t)
}
}
impl ReprError
{
/// Returns an `Error` with a message for representation errata.
///
/// # Examples
///
/// ```
/// use maraiah::err::ReprError;
///
/// assert_eq!(format!("{}", ReprError::new("TypeName", 77)),
/// "bad TypeName (77)");
/// ```
pub fn new<T: Into<i64>>(t: &'static str, n: T) -> Self
{
Self(t, n.into())
}
/// Returns an `Error` with a message for representation errata.
///
/// # Examples
///
/// ```
/// use maraiah::err::ReprError;
///
/// assert_eq!(format!("{}", ReprError::new("TypeName", 77)),
/// "bad TypeName (77)");
/// ```
pub fn new<T: Into<i64>>(t: &'static str, n: T) -> Self
{
Self(t, n.into())
}
}
impl Fail for ErrMsg {}
@ -116,34 +116,34 @@ impl Fail for ReprError {}
impl fmt::Display for ParseEnumError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "could not parse {}", self.0)
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "could not parse {}", self.0)
}
}
impl fmt::Display for ParseFlagError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "could not parse {}", self.0)
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "could not parse {}", self.0)
}
}
impl fmt::Display for ReprError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "bad {} ({})", self.0, self.1)
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "bad {} ({})", self.0, self.1)
}
}
impl fmt::Display for ErrMsg
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.write_str(self.0)
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.write_str(self.0)
}
}
#[derive(Clone, Debug)]

View File

@ -19,14 +19,14 @@ pub use std::{ffi::*, os::raw::*, ptr::{null, null_mut}};
/// assert!(!st.is_null());
///
/// unsafe {
/// assert_eq!(std::slice::from_raw_parts(st, 5), &[116, 101, 115, 116, 0]);
/// assert_eq!(std::slice::from_raw_parts(st, 5), &[116, 101, 115, 116, 0]);
/// }
/// ```
#[macro_export]
macro_rules! c_str {
($s:expr) => {
concat!($s, "\0").as_ptr() as $crate::ffi::NT
};
($s:expr) => {
concat!($s, "\0").as_ptr() as $crate::ffi::NT
};
}
/// Returns [`null`] as a [`*const c_void`].
@ -45,49 +45,49 @@ pub const fn null_mut_void() -> *mut c_void {null_mut()}
impl CStringVec
{
/// Creates a new `CStringVec` from an iterator.
#[inline]
pub fn new_from_iter<'a, I>(it: I) -> ResultS<Self>
where I: Iterator<Item = &'a str>
{
let mut v = Self::default();
/// Creates a new `CStringVec` from an iterator.
#[inline]
pub fn new_from_iter<'a, I>(it: I) -> ResultS<Self>
where I: Iterator<Item = &'a str>
{
let mut v = Self::default();
for st in it {
v.push(CString::new(st)?);
}
for st in it {
v.push(CString::new(st)?);
}
Ok(v)
}
Ok(v)
}
/// Pushes a new `CString`.
#[inline]
pub fn push(&mut self, st: CString)
{
self.cv.insert(self.cv.len() - 1, st.as_ptr());
self.sv.push(st);
}
/// Pushes a new `CString`.
#[inline]
pub fn push(&mut self, st: CString)
{
self.cv.insert(self.cv.len() - 1, st.as_ptr());
self.sv.push(st);
}
/// Returns the FFI pointer.
#[inline]
pub fn as_ptr(&self) -> *const NT {self.cv.as_ptr()}
/// Returns the FFI pointer.
#[inline]
pub fn as_ptr(&self) -> *const NT {self.cv.as_ptr()}
/// Returns the FFI pointer mutably.
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut NT {self.cv.as_mut_ptr()}
/// Returns the FFI pointer mutably.
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut NT {self.cv.as_mut_ptr()}
}
impl Default for CStringVec
{
/// Creates a new empty CStringVec.
#[inline]
fn default() -> Self {Self{sv: Vec::new(), cv: vec![null()]}}
/// Creates a new empty CStringVec.
#[inline]
fn default() -> Self {Self{sv: Vec::new(), cv: vec![null()]}}
}
/// An owned null-terminated string vector.
#[derive(Debug)]
pub struct CStringVec {
sv: Vec<CString>,
cv: Vec<NT>,
sv: Vec<CString>,
cv: Vec<NT>,
}
/// A null-terminated byte string pointer.

View File

@ -6,62 +6,62 @@ use std::{fs, path::Path, io::{SeekFrom, prelude::*}};
/// Confirms that the path `p` is a folder.
pub fn validate_folder_path(p: &str) -> ResultS<()>
{
let at = fs::metadata(p)?;
if at.is_dir() {
Ok(())
} else {
Err(err_msg("not a directory"))
}
let at = fs::metadata(p)?;
if at.is_dir() {
Ok(())
} else {
Err(err_msg("not a directory"))
}
}
/// Opens the file at `path` and skips past any macintosh headers.
pub fn open_mac<P: AsRef<Path>>(path: P) -> ResultS<fs::File>
{
let mut fp = fs::File::open(path)?;
let mut fp = fs::File::open(path)?;
machdr::skip_mac_header(&mut fp);
machdr::skip_mac_header(&mut fp);
Ok(fp)
Ok(fp)
}
impl<T> Drop for SeekBackToStart<T>
where T: Seek
where T: Seek
{
fn drop(&mut self) {if self.fl {let _ = self.seek(SeekFrom::Start(0));}}
fn drop(&mut self) {if self.fl {let _ = self.seek(SeekFrom::Start(0));}}
}
impl<T> std::ops::Deref for SeekBackToStart<T>
where T: Seek
where T: Seek
{
type Target = T;
type Target = T;
fn deref(&self) -> &Self::Target {&self.sc}
fn deref(&self) -> &Self::Target {&self.sc}
}
impl<T> std::ops::DerefMut for SeekBackToStart<T>
where T: Seek
where T: Seek
{
fn deref_mut(&mut self) -> &mut Self::Target {&mut self.sc}
fn deref_mut(&mut self) -> &mut Self::Target {&mut self.sc}
}
impl<T> SeekBackToStart<T>
where T: Seek
where T: Seek
{
/// Creates a new `SeekBackToStart` object.
pub fn new(sc: T) -> Self {Self{sc, fl: true}}
/// Creates a new `SeekBackToStart` object.
pub fn new(sc: T) -> Self {Self{sc, fl: true}}
/// Sets the seek-back flag.
pub fn set_seek(&mut self, fl: bool) {self.fl = fl;}
/// Sets the seek-back flag.
pub fn set_seek(&mut self, fl: bool) {self.fl = fl;}
/// Returns the seek-back flag.
pub fn get_seek(&self) -> bool {self.fl}
/// Returns the seek-back flag.
pub fn get_seek(&self) -> bool {self.fl}
}
/// Seeks back to the starting position of the inner object when losing scope,
/// unless a flag is set.
pub struct SeekBackToStart<T: Seek> {
sc: T,
fl: bool,
sc: T,
fl: bool,
}
// EOF

File diff suppressed because it is too large Load Diff

View File

@ -16,10 +16,10 @@ pub mod tga;
#[inline]
pub const fn r5g5b5_to_rgb8(rgb: u16) -> Color8
{
let r = (rgb >> 10) as u8 & 0x1f;
let g = (rgb >> 5) as u8 & 0x1f;
let b = rgb as u8 & 0x1f;
Color8::new(r << 3, g << 3, b << 3)
let r = (rgb >> 10) as u8 & 0x1f;
let g = (rgb >> 5) as u8 & 0x1f;
let b = rgb as u8 & 0x1f;
Color8::new(r << 3, g << 3, b << 3)
}
/// Creates a RGB16 color from a R5G5B5 format color.
@ -35,10 +35,10 @@ pub const fn r5g5b5_to_rgb8(rgb: u16) -> Color8
#[inline]
pub const fn r5g5b5_to_rgb16(rgb: u16) -> Color16
{
let r = rgb >> 10 & 0x1f;
let g = rgb >> 5 & 0x1f;
let b = rgb & 0x1f;
Color16::new(r << 11, g << 11, b << 11)
let r = rgb >> 10 & 0x1f;
let g = rgb >> 5 & 0x1f;
let b = rgb & 0x1f;
Color16::new(r << 11, g << 11, b << 11)
}
/// Creates a RGB16 color from a RGB8 format color.
@ -55,174 +55,174 @@ pub const fn r5g5b5_to_rgb16(rgb: u16) -> Color16
/// ```
pub fn rgb8_to_rgb16(cr: Color8) -> Color16
{
Color16::new(cr.r(), cr.g(), cr.b())
Color16::new(cr.r(), cr.g(), cr.b())
}
/// A generic color matrix image.
pub trait Image
{
/// The type of color this image uses for each pixel.
type Output: Color;
/// 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 width of the image.
fn w(&self) -> usize;
/// Returns the height of the image.
fn h(&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
///
/// 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;
/// Returns the color of the pixel at column `x` at row `y`.
///
/// # Panics
///
/// 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() {
Some(self.index(x, y))
} else {
None
}
}
/// 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() {
Some(self.index(x, y))
} else {
None
}
}
}
/// A generic color matrix image, which may be mutated.
pub trait ImageMut: Image
{
/// Returns the color of the pixel at column `x` at row `y`.
///
/// # Panics
///
/// Panics if `x` is greater than the width of the image or `y` is greater
/// than the height of the image.
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output;
/// Returns the color of the pixel at column `x` at row `y`.
///
/// # Panics
///
/// Panics if `x` is greater than the width of the image or `y` is greater
/// than the height of the image.
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output;
/// The same as `index_mut`, but will not panic if out of bounds.
fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut Self::Output>
{
if x < self.w() && y < self.h() {
Some(self.index_mut(x, y))
} else {
None
}
}
/// The same as `index_mut`, but will not panic if out of bounds.
fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut Self::Output>
{
if x < self.w() && y < self.h() {
Some(self.index_mut(x, y))
} else {
None
}
}
}
/// Any color which may be represented as RGBA16.
pub trait Color: Sized + Copy + Clone + Eq + PartialEq
{
/// Returns the red component.
fn r(&self) -> u16;
/// Returns the red component.
fn r(&self) -> u16;
/// Returns the green component.
fn g(&self) -> u16;
/// Returns the green component.
fn g(&self) -> u16;
/// Returns the blue component.
fn b(&self) -> u16;
/// Returns the blue component.
fn b(&self) -> u16;
/// Returns the alpha component.
fn a(&self) -> u16;
/// Returns the alpha component.
fn a(&self) -> u16;
}
impl Image16
{
/// Creates a new Image16 with no canvas.
pub fn new(w: usize, h: usize) -> Self
{
Self{w, h, cr: Vec::with_capacity(w * h)}
}
/// Creates a new Image16 with no canvas.
pub fn new(w: usize, h: usize) -> Self
{
Self{w, h, cr: Vec::with_capacity(w * h)}
}
/// Creates a new Image16 with an empty canvas.
pub fn new_empty(w: usize, h: usize) -> Self
{
Self{w, h, cr: vec![Color16::new(0, 0, 0); w * h]}
}
/// Creates a new Image16 with an empty canvas.
pub fn new_empty(w: usize, h: usize) -> Self
{
Self{w, h, cr: vec![Color16::new(0, 0, 0); w * h]}
}
}
impl Image for Image16
{
type Output = Color16;
type Output = Color16;
fn w(&self) -> usize {self.w}
fn h(&self) -> usize {self.h}
fn w(&self) -> usize {self.w}
fn h(&self) -> usize {self.h}
fn index(&self, x: usize, y: usize) -> &Self::Output
{
&self.cr[x + y * self.w]
}
fn index(&self, x: usize, y: usize) -> &Self::Output
{
&self.cr[x + y * self.w]
}
}
impl ImageMut for Image16
{
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
{
&mut self.cr[x + y * self.w]
}
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
{
&mut self.cr[x + y * self.w]
}
}
impl Image8
{
/// Creates a new Image8 with no canvas.
pub fn new(w: usize, h: usize) -> Self
{
Self{w, h, cr: Vec::with_capacity(w * h)}
}
/// Creates a new Image8 with no canvas.
pub fn new(w: usize, h: usize) -> Self
{
Self{w, h, cr: Vec::with_capacity(w * h)}
}
/// Creates a new Image8 with an empty canvas.
pub fn new_empty(w: usize, h: usize) -> Self
{
Self{w, h, cr: vec![Color8::new(0, 0, 0); w * h]}
}
/// Creates a new Image8 with an empty canvas.
pub fn new_empty(w: usize, h: usize) -> Self
{
Self{w, h, cr: vec![Color8::new(0, 0, 0); w * h]}
}
}
impl Image for Image8
{
type Output = Color8;
type Output = Color8;
fn w(&self) -> usize {self.w}
fn h(&self) -> usize {self.h}
fn w(&self) -> usize {self.w}
fn h(&self) -> usize {self.h}
fn index(&self, x: usize, y: usize) -> &Self::Output
{
&self.cr[x + y * self.w]
}
fn index(&self, x: usize, y: usize) -> &Self::Output
{
&self.cr[x + y * self.w]
}
}
impl ImageMut for Image8
{
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
{
&mut self.cr[x + y * self.w]
}
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
{
&mut self.cr[x + y * self.w]
}
}
impl Color16
{
pub const fn new(r: u16, g: u16, b: u16) -> Self {Self(r, g, b)}
pub const fn new(r: u16, g: u16, b: u16) -> Self {Self(r, g, b)}
}
impl Color for Color16
{
fn r(&self) -> u16 {self.0}
fn g(&self) -> u16 {self.1}
fn b(&self) -> u16 {self.2}
fn a(&self) -> u16 {u16::max_value()}
fn r(&self) -> u16 {self.0}
fn g(&self) -> u16 {self.1}
fn b(&self) -> u16 {self.2}
fn a(&self) -> u16 {u16::max_value()}
}
impl Color8
{
pub const fn new(r: u8, g: u8, b: u8) -> Self {Self(r, g, b)}
pub const fn new(r: u8, g: u8, b: u8) -> Self {Self(r, g, b)}
}
impl Color for Color8
{
fn r(&self) -> u16 {u16::from(self.0) << 8}
fn g(&self) -> u16 {u16::from(self.1) << 8}
fn b(&self) -> u16 {u16::from(self.2) << 8}
fn a(&self) -> u16 {u16::max_value()}
fn r(&self) -> u16 {u16::from(self.0) << 8}
fn g(&self) -> u16 {u16::from(self.1) << 8}
fn b(&self) -> u16 {u16::from(self.2) << 8}
fn a(&self) -> u16 {u16::max_value()}
}
/// An RGB16 color.
@ -239,22 +239,22 @@ pub struct Color8(u8, u8, u8);
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Image16 {
w: usize,
h: usize,
w: usize,
h: usize,
/// The raw color data for this image.
pub cr: Vec<Color16>,
/// The raw color data for this image.
pub cr: Vec<Color16>,
}
/// An RGB8 image.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Image8 {
w: usize,
h: usize,
w: usize,
h: usize,
/// The raw color data for this image.
pub cr: Vec<Color8>,
/// The raw color data for this image.
pub cr: Vec<Color8>,
}
// EOF

View File

@ -9,109 +9,109 @@ use crate::{bin::*, err::*, image::*};
/// Load a `PICT` image.
pub fn read(b: &[u8]) -> ResultS<Image8>
{
read_data! {
endian: BIG, buf: b, size: 10, start: 0, data {
let h = u16[6] usize;
let w = u16[8] usize;
}
}
read_data! {
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 {
bail!("image is too large");
}
if w * h > 16_000_000 {
bail!("image is too large");
}
let im = Image8::new(w, h);
let im = Image8::new(w, h);
let mut p = 10; // size of header
let mut p = 10; // size of header
while p < b.len() {
read_data! {
endian: BIG, buf: b, size: 2, start: p, data {
let op = u16[0];
}
}
while p < b.len() {
read_data! {
endian: BIG, buf: b, size: 2, start: p, data {
let op = u16[0];
}
}
p += 2;
p += 2;
match op {
0x0098 => {
// PackBitsRect
return pm::area::read(im, &b[p..], true, false);
}
0x0099 => {
// PackBitsRgn
return pm::area::read(im, &b[p..], true, true);
}
0x009a => {
// DirectBitsRect
return pm::area::read(im, &b[p..], false, false);
}
0x009b => {
// DirectBitsRgn
return pm::area::read(im, &b[p..], false, true);
}
0x8200 => {
// CompressedQuickTime
unimplemented!();
}
0x00ff => {
// OpEndPic
break;
}
// help i'm trapped in an awful metafile format from the 80s
0x0000 | // NoOp
0x001c | // HiliteMode
0x001e | // DefHilite
0x0038 | // FrameSameRect
0x0039 | // PaintSameRect
0x003a | // EraseSameRect
0x003b | // InvertSameRect
0x003c | // FillSameRect
0x8000 | // Reserved
0x8100 => (), // Reserved
0x0003 | // TxFont
0x0004 | // TxFace
0x0005 | // TxMode
0x0008 | // PnMode
0x000d | // TxSize
0x0011 | // VersionOp
0x0015 | // PnLocHFrac
0x0016 | // ChExtra
0x0023 | // ShortLineFrom
0x00a0 => p += 2, // ShortComment
0x0006 | // SpExtra
0x0007 | // PnSize
0x000b | // OvSize
0x000c | // Origin
0x000e | // FgCol
0x000f | // BkCol
0x0021 => p += 4, // LineFrom
0x001a | // RGBFgCol
0x001b | // RGBBkCol
0x001d | // TxRatio
0x0022 => p += 6, // ShortLine
0x0002 | // BkPat
0x0009 | // PnPat
0x0010 | // TxRatio
0x0020 | // Line
0x002e | // GlyphState
0x0030 | // FrameRect
0x0031 | // PaintRect
0x0032 | // EraseRect
0x0033 | // InvertRect
0x0034 => p += 8, // FillRect
0x002d => p += 10, // LineJustify
0x0001 => p += usize::from(u16b(&b[p.. ]) & !1), // Clip
0x00a1 => p += usize::from(u16b(&b[p+2..]) & !1) + 2, // LongComment
0x100..=
0x7fff => p += usize::from(op >> 8) * 2, // Reserved
_ => {
bail!("invalid op in PICT");
}
}
}
match op {
0x0098 => {
// PackBitsRect
return pm::area::read(im, &b[p..], true, false);
}
0x0099 => {
// PackBitsRgn
return pm::area::read(im, &b[p..], true, true);
}
0x009a => {
// DirectBitsRect
return pm::area::read(im, &b[p..], false, false);
}
0x009b => {
// DirectBitsRgn
return pm::area::read(im, &b[p..], false, true);
}
0x8200 => {
// CompressedQuickTime
unimplemented!();
}
0x00ff => {
// OpEndPic
break;
}
// help i'm trapped in an awful metafile format from the 80s
0x0000 | // NoOp
0x001c | // HiliteMode
0x001e | // DefHilite
0x0038 | // FrameSameRect
0x0039 | // PaintSameRect
0x003a | // EraseSameRect
0x003b | // InvertSameRect
0x003c | // FillSameRect
0x8000 | // Reserved
0x8100 => (), // Reserved
0x0003 | // TxFont
0x0004 | // TxFace
0x0005 | // TxMode
0x0008 | // PnMode
0x000d | // TxSize
0x0011 | // VersionOp
0x0015 | // PnLocHFrac
0x0016 | // ChExtra
0x0023 | // ShortLineFrom
0x00a0 => p += 2, // ShortComment
0x0006 | // SpExtra
0x0007 | // PnSize
0x000b | // OvSize
0x000c | // Origin
0x000e | // FgCol
0x000f | // BkCol
0x0021 => p += 4, // LineFrom
0x001a | // RGBFgCol
0x001b | // RGBBkCol
0x001d | // TxRatio
0x0022 => p += 6, // ShortLine
0x0002 | // BkPat
0x0009 | // PnPat
0x0010 | // TxRatio
0x0020 | // Line
0x002e | // GlyphState
0x0030 | // FrameRect
0x0031 | // PaintRect
0x0032 | // EraseRect
0x0033 | // InvertRect
0x0034 => p += 8, // FillRect
0x002d => p += 10, // LineJustify
0x0001 => p += usize::from(u16b(&b[p.. ]) & !1), // Clip
0x00a1 => p += usize::from(u16b(&b[p+2..]) & !1) + 2, // LongComment
0x100..=
0x7fff => p += usize::from(op >> 8) * 2, // Reserved
_ => {
bail!("invalid op in PICT");
}
}
}
Err(err_msg("no image in data"))
Err(err_msg("no image in data"))
}
// EOF

View File

@ -5,38 +5,38 @@ use crate::{err::*, image::*};
/// Read a `ColorTable` structure.
pub fn read(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
{
read_data! {
endian: BIG, buf: b, size: 8, start: 0, data {
let dev = u16[4];
let num = u16[6] usize;
}
}
read_data! {
endian: BIG, buf: b, size: 8, start: 0, data {
let dev = u16[4];
let num = u16[6] usize;
}
}
let dev = dev & 0x8000 != 0;
let num = num + 1;
let dev = dev & 0x8000 != 0;
let num = num + 1;
let mut p = 8;
let mut clut = vec![Color8::new(0, 0, 0); num];
let mut p = 8;
let mut clut = vec![Color8::new(0, 0, 0); num];
for i in 0..num {
read_data! {
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];
}
}
for i in 0..num {
read_data! {
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
let n = if dev {i} else {n};
// with device mapping, we ignore the index entirely
let n = if dev {i} else {n};
*ok!(clut.get_mut(n), "invalid index")? = Color8::new(r, g, b);
*ok!(clut.get_mut(n), "invalid index")? = Color8::new(r, g, b);
p += 8;
}
p += 8;
}
Ok((clut, p))
Ok((clut, p))
}
// EOF

View File

@ -5,17 +5,17 @@ use crate::{err::*, image::{*, pict::pm}};
/// Process a `CopyBits` operation.
pub fn read(im: Image8, b: &[u8], pack: bool, clip: bool) -> ResultS<Image8>
{
let p = if pack {0} else {4};
let (b, hdr) = pm::head::read(&b[p..], pack, clip, &im)?;
let p = if pack {0} else {4};
let (b, hdr) = pm::head::read(&b[p..], pack, clip, &im)?;
match hdr.depth {
pm::head::Depth::_1 |
pm::head::Depth::_2 |
pm::head::Depth::_4 |
pm::head::Depth::_8 => pm::ind::read(im, b, hdr),
pm::head::Depth::_16 => pm::r5g5b5::read(im, b, hdr),
pm::head::Depth::_32 => pm::rgb8::read(im, b, hdr),
}
match hdr.depth {
pm::head::Depth::_1 |
pm::head::Depth::_2 |
pm::head::Depth::_4 |
pm::head::Depth::_8 => pm::ind::read(im, b, hdr),
pm::head::Depth::_16 => pm::r5g5b5::read(im, b, hdr),
pm::head::Depth::_32 => pm::rgb8::read(im, b, hdr),
}
}
// EOF

View File

@ -8,79 +8,79 @@ pub fn read<'a>(b: &'a [u8],
clip: bool,
im: &Image8) -> ResultS<(&'a [u8], Header)>
{
read_data! {
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;
}
}
read_data! {
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;
}
}
if pt_fl & 0x8000 == 0 {
bail!("PICT1 not supported");
}
if pt_fl & 0x8000 == 0 {
bail!("PICT1 not supported");
}
if right - left != im.w() || bottom - top != im.h() {
bail!("image bounds are incorrect");
}
if right - left != im.w() || bottom - top != im.h() {
bail!("image bounds are incorrect");
}
let mut p = 46;
let mut p = 46;
// get CLUT if packed
let clut = if pack {
let (clut, sz) = pict::clut::read(&b[p..])?;
p += sz;
Some(clut)
} else {
None
};
// get CLUT if packed
let clut = if pack {
let (clut, sz) = pict::clut::read(&b[p..])?;
p += sz;
Some(clut)
} else {
None
};
p += 18; // srcRect, dstRect, mode
p += 18; // srcRect, dstRect, mode
if clip {
p += usize::from(u16b(&b[p..])); // maskRgn
}
if clip {
p += usize::from(u16b(&b[p..])); // maskRgn
}
let rle = pack_t == PackType::Default ||
pack_t == PackType::Rle16 && depth == Depth::_16 ||
pack_t == PackType::Rle32 && depth == Depth::_32;
let rle = pack_t == PackType::Default ||
pack_t == PackType::Rle16 && depth == Depth::_16 ||
pack_t == PackType::Rle32 && depth == Depth::_32;
let pitch = usize::from(pt_fl & 0x3FFF);
let pitch = usize::from(pt_fl & 0x3FFF);
Ok((&b[p..], Header{pitch, pack_t, depth, clut, rle}))
Ok((&b[p..], Header{pitch, pack_t, depth, clut, rle}))
}
pub struct Header {
pub pitch: usize,
pub pack_t: PackType,
pub depth: Depth,
pub clut: Option<Vec<Color8>>,
pub rle: bool,
pub pitch: usize,
pub pack_t: PackType,
pub depth: Depth,
pub clut: Option<Vec<Color8>>,
pub rle: bool,
}
c_enum! {
pub enum Depth: u16 {
_1 = 1,
_2 = 2,
_4 = 4,
_8 = 8,
_16 = 16,
_32 = 32,
}
pub enum Depth: u16 {
_1 = 1,
_2 = 2,
_4 = 4,
_8 = 8,
_16 = 16,
_32 = 32,
}
}
c_enum! {
pub enum PackType: u16 {
Default = 0,
None = 1,
NoPad = 2,
Rle16 = 3,
Rle32 = 4,
}
pub enum PackType: u16 {
Default = 0,
None = 1,
NoPad = 2,
Rle16 = 3,
Rle32 = 4,
}
}
// EOF

View File

@ -7,81 +7,80 @@ pub fn read(mut im: Image8,
b: &[u8],
hdr: pm::head::Header) -> ResultS<Image8>
{
let clut = ok!(hdr.clut, "no CLUT in indexed mode")?;
let mut p = 0;
let clut = ok!(hdr.clut, "no CLUT in indexed mode")?;
let mut p = 0;
if hdr.pitch < 8 && hdr.depth == pm::head::Depth::_8 {
// uncompressed 8-bit colormap indices
for _ in 0..im.h() {
for _ in 0..im.w() {
let idx = usize::from(b[p]);
if hdr.pitch < 8 && hdr.depth == pm::head::Depth::_8 {
// uncompressed 8-bit colormap indices
for _ in 0..im.h() {
for _ in 0..im.w() {
let idx = usize::from(b[p]);
im.cr.push(ok!(clut.get(idx), "invalid index")?.clone());
im.cr.push(ok!(clut.get(idx), "bad index")?.clone());
p += 1;
}
}
p += 1;
}
}
Ok(im)
} else if hdr.rle {
// RLE compressed 1, 2, 4 or 8 bit colormap indices
for _ in 0..im.h() {
let (d, pp) = rle::read::<u8>(&b[p..], hdr.pitch)?;
Ok(im)
} else if hdr.rle {
// RLE compressed 1, 2, 4 or 8 bit colormap indices
for _ in 0..im.h() {
let (d, pp) = rle::read::<u8>(&b[p..], hdr.pitch)?;
let d = if hdr.depth < pm::head::Depth::_8 {
expand_data(d, hdr.depth)?
} else {
d
};
let d = if hdr.depth < pm::head::Depth::_8 {
expand_data(d, hdr.depth)?
} else {
d
};
check_data(&d, im.w())?;
check_data(&d, im.w())?;
p += pp;
p += pp;
for &idx in &d {
im.cr
.push(ok!(clut.get(usize::from(idx)), "invalid index")?.clone());
}
}
for &idx in &d {
im.cr.push(ok!(clut.get(usize::from(idx)), "bad index")?.clone());
}
}
Ok(im)
} else {
bail!("invalid configuration")
}
Ok(im)
} else {
bail!("invalid configuration")
}
}
/// Expand packed pixel data based on bit depth.
pub fn expand_data(b: Vec<u8>, depth: pm::head::Depth) -> ResultS<Vec<u8>>
{
let mut o = Vec::with_capacity(match depth {
pm::head::Depth::_4 => b.len() * 2,
pm::head::Depth::_2 => b.len() * 4,
pm::head::Depth::_1 => b.len() * 8,
_ => bail!("invalid bit depth"),
});
let mut o = Vec::with_capacity(match depth {
pm::head::Depth::_4 => b.len() * 2,
pm::head::Depth::_2 => b.len() * 4,
pm::head::Depth::_1 => b.len() * 8,
_ => bail!("invalid bit depth"),
});
for ch in b {
match depth {
pm::head::Depth::_4 => {
for i in (0..=1).rev() {
o.push(ch >> (i * 4) & 0xF_u8);
}
}
pm::head::Depth::_2 => {
for i in (0..=3).rev() {
o.push(ch >> (i * 2) & 0x3_u8);
}
}
pm::head::Depth::_1 => {
for i in (0..=7).rev() {
o.push(ch >> i & 0x1_u8);
}
}
_ => bail!("invalid bit depth"),
}
}
for ch in b {
match depth {
pm::head::Depth::_4 => {
for i in (0..=1).rev() {
o.push(ch >> (i * 4) & 0xF_u8);
}
}
pm::head::Depth::_2 => {
for i in (0..=3).rev() {
o.push(ch >> (i * 2) & 0x3_u8);
}
}
pm::head::Depth::_1 => {
for i in (0..=7).rev() {
o.push(ch >> i & 0x1_u8);
}
}
_ => bail!("invalid bit depth"),
}
}
Ok(o)
Ok(o)
}
// EOF

View File

@ -7,38 +7,38 @@ pub fn read(mut im: Image8,
b: &[u8],
hdr: pm::head::Header) -> ResultS<Image8>
{
let mut p = 0;
let mut p = 0;
if hdr.pitch < 8 || hdr.pack_t == pm::head::PackType::None {
// uncompressed R5G5B5
for _ in 0..im.h() {
for _ in 0..im.w() {
let cr = u16b(&b[p..]);
if hdr.pitch < 8 || hdr.pack_t == pm::head::PackType::None {
// uncompressed R5G5B5
for _ in 0..im.h() {
for _ in 0..im.w() {
let cr = u16b(&b[p..]);
im.cr.push(r5g5b5_to_rgb8(cr));
p += 2;
}
}
im.cr.push(r5g5b5_to_rgb8(cr));
p += 2;
}
}
Ok(im)
} else if hdr.rle {
// RLE compressed R5G5B5
for _ in 0..im.h() {
let (d, pp) = rle::read::<u16>(&b[p..], hdr.pitch)?;
Ok(im)
} else if hdr.rle {
// RLE compressed R5G5B5
for _ in 0..im.h() {
let (d, pp) = rle::read::<u16>(&b[p..], hdr.pitch)?;
check_data(&d, im.w())?;
check_data(&d, im.w())?;
p += pp;
p += pp;
for &cr in &d {
im.cr.push(r5g5b5_to_rgb8(cr));
}
}
for &cr in &d {
im.cr.push(r5g5b5_to_rgb8(cr));
}
}
Ok(im)
} else {
bail!("invalid configuration")
}
Ok(im)
} else {
bail!("invalid configuration")
}
}
// EOF

View File

@ -7,56 +7,56 @@ pub fn read(mut im: Image8,
b: &[u8],
hdr: pm::head::Header) -> ResultS<Image8>
{
let mut p = 0;
let mut p = 0;
if hdr.pitch < 8 ||
hdr.pack_t == pm::head::PackType::None ||
hdr.pack_t == pm::head::PackType::NoPad
{
// uncompressed RGB8 or XRGB8
for _ in 0..im.h() {
for _ in 0..im.w() {
if hdr.pack_t != pm::head::PackType::NoPad {
p += 1;
}
if hdr.pitch < 8 ||
hdr.pack_t == pm::head::PackType::None ||
hdr.pack_t == pm::head::PackType::NoPad
{
// uncompressed RGB8 or XRGB8
for _ in 0..im.h() {
for _ in 0..im.w() {
if hdr.pack_t != pm::head::PackType::NoPad {
p += 1;
}
read_data! {
endian: BIG, buf: b, size: 3, start: p, data {
let r = u8[0];
let g = u8[1];
let b = u8[2];
}
}
read_data! {
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));
im.cr.push(Color8::new(r, g, b));
p += 3;
}
}
p += 3;
}
}
Ok(im)
} else if hdr.rle {
// RLE compressed RGB8
let pitch = hdr.pitch - im.w(); // remove padding byte from pitch
for _ in 0..im.h() {
let (d, pp) = rle::read::<u8>(&b[p..], pitch)?;
Ok(im)
} else if hdr.rle {
// RLE compressed RGB8
let pitch = hdr.pitch - im.w(); // remove padding byte from pitch
for _ in 0..im.h() {
let (d, pp) = rle::read::<u8>(&b[p..], pitch)?;
check_data(&d, im.w() * 3)?;
check_data(&d, im.w() * 3)?;
p += pp;
p += pp;
for x in 0..im.w() {
let r = d[x];
let g = d[x * 2];
let b = d[x * 3];
im.cr.push(Color8::new(r, g, b));
}
}
for x in 0..im.w() {
let r = d[x];
let g = d[x * 2];
let b = d[x * 3];
im.cr.push(Color8::new(r, g, b));
}
}
Ok(im)
} else {
bail!("invalid configuration")
}
Ok(im)
} else {
bail!("invalid configuration")
}
}
// EOF

View File

@ -4,91 +4,91 @@ use crate::{bin::*, err::*};
/// Read run-length encoded data.
pub fn read<T>(b: &[u8], pitch: usize) -> ResultS<(Vec<T>, usize)>
where T: ReadRleData
where T: ReadRleData
{
let mut p = 0;
let mut o = Vec::with_capacity(pitch);
let mut p = 0;
let mut o = Vec::with_capacity(pitch);
let sz = if pitch > 250 {
(usize::from(u16b(b)) + 2, p += 2).0
} else {
(usize::from(b[0]) + 1, p += 1).0
};
let sz = if pitch > 250 {
(usize::from(u16b(b)) + 2, p += 2).0
} else {
(usize::from(b[0]) + 1, p += 1).0
};
while p < sz {
let szf = b[p];
let cmp = szf & 0x80 != 0;
let len = usize::from(if cmp {!szf + 2} else {szf + 1});
while p < sz {
let szf = b[p];
let cmp = szf & 0x80 != 0;
let len = usize::from(if cmp {!szf + 2} else {szf + 1});
p += 1;
o.reserve(len);
p += 1;
o.reserve(len);
T::read_rle_data(b, &mut p, cmp, len, &mut o);
}
T::read_rle_data(b, &mut p, cmp, len, &mut o);
}
if o.len() == pitch {
Ok((o, p))
} else {
Err(err_msg("incorrect size for compressed scanline"))
}
if o.len() == pitch {
Ok((o, p))
} else {
Err(err_msg("incorrect size for compressed scanline"))
}
}
pub trait ReadRleData: Sized
{
// Read a sequence of packed RLE data.
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>);
// Read a sequence of packed RLE data.
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>);
}
impl ReadRleData for u16
{
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>)
{
if cmp {
let d = u16b(&b[*p..*p + 2]);
*p += 2;
for _ in 0..len {
out.push(d);
}
} else {
for _ in 0..len {
let d = u16b(&b[*p..*p + 2]);
*p += 2;
out.push(d);
}
}
}
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>)
{
if cmp {
let d = u16b(&b[*p..*p + 2]);
*p += 2;
for _ in 0..len {
out.push(d);
}
} else {
for _ in 0..len {
let d = u16b(&b[*p..*p + 2]);
*p += 2;
out.push(d);
}
}
}
}
impl ReadRleData for u8
{
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>)
{
if cmp {
let d = b[*p];
*p += 1;
for _ in 0..len {
out.push(d);
}
} else {
for _ in 0..len {
let d = b[*p];
*p += 1;
out.push(d);
}
}
}
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>)
{
if cmp {
let d = b[*p];
*p += 1;
for _ in 0..len {
out.push(d);
}
} else {
for _ in 0..len {
let d = b[*p];
*p += 1;
out.push(d);
}
}
}
}
// EOF

View File

@ -10,60 +10,60 @@ use std::io;
/// Errors if `out` cannot be written to.
pub fn write_ppm(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
{
write!(out, "P3\n{} {}\n{}\n", im.w(), im.h(), u16::max_value())?;
write!(out, "P3\n{} {}\n{}\n", im.w(), im.h(), u16::max_value())?;
for y in 0..im.h() {
for x in 0..im.w() {
let cr = im.index(x, y);
write!(out, "{} {} {} ", cr.r(), cr.g(), cr.b())?;
}
for y in 0..im.h() {
for x in 0..im.w() {
let cr = im.index(x, y);
write!(out, "{} {} {} ", cr.r(), cr.g(), cr.b())?;
}
out.write_all(b"\n")?;
}
out.write_all(b"\n")?;
}
Ok(())
Ok(())
}
/// Reads a PPM file into an image.
pub fn read_ppm(inp: &[u8]) -> ResultS<Image16>
{
let mut it = inp.split(|&n| n == b'\n' || n == b'\r' || n == b' ');
let mut it = inp.split(|&n| n == b'\n' || n == b'\r' || n == b' ');
if ok!(it.next(), "no magic number")? != b"P3" {
bail!("not P3 format");
}
if ok!(it.next(), "no magic number")? != b"P3" {
bail!("not P3 format");
}
let mut get_num = move || -> ResultS<u16> {
let st = loop {
match ok!(it.next(), "no more strings")? {
b"" => {}
st => break st
}
};
let st = unsafe {std::str::from_utf8_unchecked(st)};
let nu = u16::from_str_radix(st, 10)?;
Ok(nu)
};
let mut get_num = move || -> ResultS<u16> {
let st = loop {
match ok!(it.next(), "no more strings")? {
b"" => {}
st => break st
}
};
let st = unsafe {std::str::from_utf8_unchecked(st)};
let nu = u16::from_str_radix(st, 10)?;
Ok(nu)
};
let width = get_num()?;
let height = get_num()?;
let depth = i64::from(get_num()?);
let width = get_num()?;
let height = get_num()?;
let depth = i64::from(get_num()?);
let mut im = Image16::new(usize::from(width), usize::from(height));
let mut im = Image16::new(usize::from(width), usize::from(height));
for _ in 0..height * width {
let r = FixedLong::from_int(get_num()?.into());
let g = FixedLong::from_int(get_num()?.into());
let b = FixedLong::from_int(get_num()?.into());
for _ in 0..height * width {
let r = FixedLong::from_int(get_num()?.into());
let g = FixedLong::from_int(get_num()?.into());
let b = FixedLong::from_int(get_num()?.into());
let r = (r / depth * 0xFFFF).integ() as u16;
let g = (g / depth * 0xFFFF).integ() as u16;
let b = (b / depth * 0xFFFF).integ() as u16;
let r = (r / depth * 0xFFFF).integ() as u16;
let g = (g / depth * 0xFFFF).integ() as u16;
let b = (b / depth * 0xFFFF).integ() as u16;
im.cr.push(Color16::new(r, g, b));
}
im.cr.push(Color16::new(r, g, b));
}
Ok(im)
Ok(im)
}
// EOF

View File

@ -10,32 +10,32 @@ use std::io;
/// Errors if `out` cannot be written to.
pub fn write_tga(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
{
// id len, color map type, image type
out.write_all(&[0, 0, 2])?;
// color map spec
out.write_all(&[0, 0, 0, 0, 0])?;
// x origin
out.write_all(&[0, 0])?;
// y origin
out.write_all(&[0, 0])?;
// width
out.write_all(&u16::to_le_bytes(im.w() as u16))?;
// height
out.write_all(&u16::to_le_bytes(im.h() as u16))?;
// depth, descriptor
out.write_all(&[32, 0])?;
// id len, color map type, image type
out.write_all(&[0, 0, 2])?;
// color map spec
out.write_all(&[0, 0, 0, 0, 0])?;
// x origin
out.write_all(&[0, 0])?;
// y origin
out.write_all(&[0, 0])?;
// width
out.write_all(&u16::to_le_bytes(im.w() as u16))?;
// height
out.write_all(&u16::to_le_bytes(im.h() as u16))?;
// depth, descriptor
out.write_all(&[32, 0])?;
for y in (0..im.h()).rev() {
for x in 0..im.w() {
let cr = im.index(x, y);
out.write_all(&[(cr.b() >> 8) as u8,
(cr.g() >> 8) as u8,
(cr.r() >> 8) as u8,
(cr.a() >> 8) as u8])?;
}
}
for y in (0..im.h()).rev() {
for x in 0..im.w() {
let cr = im.index(x, y);
out.write_all(&[(cr.b() >> 8) as u8,
(cr.g() >> 8) as u8,
(cr.r() >> 8) as u8,
(cr.a() >> 8) as u8])?;
}
}
Ok(())
Ok(())
}
// EOF

View File

@ -5,112 +5,112 @@ use std::io::{SeekFrom, prelude::*};
/// Skips over an Apple Single header. Returns true if one was found.
pub fn skip_apple_single<R>(fp: &mut R) -> bool
where R: Read + Seek
where R: Read + Seek
{
let mut fp = SeekBackToStart::new(fp);
let mut fp = SeekBackToStart::new(fp);
let mut magic = [0; 8];
let magic = if fp.read(&mut magic).is_ok() {magic} else {return false;};
let mut magic = [0; 8];
let magic = if fp.read(&mut magic).is_ok() {magic} else {return false;};
// check magic numbers
if magic != [0, 5, 22, 0, 0, 2, 0, 0] {
return false;
}
// check magic numbers
if magic != [0, 5, 22, 0, 0, 2, 0, 0] {
return false;
}
let mut num = [0; 2];
let num = if fp.read(&mut num).is_ok() {num} else {return false;};
let num = u64::from(u16::from_be_bytes(num));
let mut num = [0; 2];
let num = if fp.read(&mut num).is_ok() {num} else {return false;};
let num = u64::from(u16::from_be_bytes(num));
if fp.seek(SeekFrom::Start(26 + 12 * num)).is_err() |
fp.seek(SeekFrom::Start(26)).is_err() {
return false;
}
if fp.seek(SeekFrom::Start(26 + 12 * num)).is_err() |
fp.seek(SeekFrom::Start(26)).is_err() {
return false;
}
// get the resource fork (entity 1)
for _ in 0..num {
let mut ent = [0; 4];
let mut ofs = [0; 4];
let mut len = [0; 4];
let ent = if fp.read(&mut ent).is_ok() {ent} else {return false;};
let ofs = if fp.read(&mut ofs).is_ok() {ofs} else {return false;};
let len = if fp.read(&mut len).is_ok() {len} else {return false;};
let ent = u32::from_be_bytes(ent);
let ofs = u64::from(u32::from_be_bytes(ofs));
let len = u64::from(u32::from_be_bytes(len));
// get the resource fork (entity 1)
for _ in 0..num {
let mut ent = [0; 4];
let mut ofs = [0; 4];
let mut len = [0; 4];
let ent = if fp.read(&mut ent).is_ok() {ent} else {return false;};
let ofs = if fp.read(&mut ofs).is_ok() {ofs} else {return false;};
let len = if fp.read(&mut len).is_ok() {len} else {return false;};
let ent = u32::from_be_bytes(ent);
let ofs = u64::from(u32::from_be_bytes(ofs));
let len = u64::from(u32::from_be_bytes(len));
if ent == 1 {
if fp.seek(SeekFrom::Start(ofs + len)).is_ok() &
fp.seek(SeekFrom::Start(ofs)).is_ok() {
fp.set_seek(false);
return true;
} else {
return false;
}
}
}
if ent == 1 {
if fp.seek(SeekFrom::Start(ofs + len)).is_ok() &
fp.seek(SeekFrom::Start(ofs)).is_ok() {
fp.set_seek(false);
return true;
} else {
return false;
}
}
}
// no resource fork
false
// no resource fork
false
}
/// Skips over a Mac Binary II header. Returns true if one was found.
pub fn skip_macbin<R>(fp: &mut R) -> bool
where R: Read + Seek
where R: Read + Seek
{
let mut fp = SeekBackToStart::new(fp);
let mut fp = SeekBackToStart::new(fp);
let mut head = [0; 128];
let head = if fp.read(&mut head).is_ok() {head} else {return false;};
let mut head = [0; 128];
let head = if fp.read(&mut head).is_ok() {head} else {return false;};
// check legacy version, length, zero fill, and macbin2 version. I swear,
// this isn't *completely* magic
if head[0] != 0 || head[1] > 63 || head[74] != 0 || head[123] > 129 {
return false;
}
// check legacy version, length, zero fill, and macbin2 version. I swear,
// this isn't *completely* magic
if head[0] != 0 || head[1] > 63 || head[74] != 0 || head[123] > 129 {
return false;
}
let mut crc = 0;
let mut crc = 0;
// check header crc
for &byte in head.iter().take(124) {
for j in 8..16 {
let d = u16::from(byte) << j;
// check header crc
for &byte in head.iter().take(124) {
for j in 8..16 {
let d = u16::from(byte) << j;
if (d ^ crc) & 0x8000 == 0 {
crc <<= 1;
} else {
crc = crc << 1 ^ 0x1021;
}
}
}
if (d ^ crc) & 0x8000 == 0 {
crc <<= 1;
} else {
crc = crc << 1 ^ 0x1021;
}
}
}
// if ok, resource fork follows
if crc == u16::from_be_bytes([head[124], head[125]]) {
fp.set_seek(false);
true
} else {
false
}
// if ok, resource fork follows
if crc == u16::from_be_bytes([head[124], head[125]]) {
fp.set_seek(false);
true
} else {
false
}
}
/// Reads a `MacBin` or `AppleSingle` header if there is one and skips past it
/// from the start of the header to the resource fork (if one is found.) Returns
/// true if either one was found.
pub fn skip_mac_header<R>(fp: &mut R) -> bool
where R: Read + Seek
where R: Read + Seek
{
if skip_macbin(fp) {
return true;
}
if skip_macbin(fp) {
return true;
}
let _ = fp.seek(SeekFrom::Start(0));
let _ = fp.seek(SeekFrom::Start(0));
if skip_apple_single(fp) {
return true;
}
if skip_apple_single(fp) {
return true;
}
let _ = fp.seek(SeekFrom::Start(0));
let _ = fp.seek(SeekFrom::Start(0));
false
false
}
// EOF

View File

@ -5,22 +5,22 @@ use crate::err::*;
/// Reads an `ambi` chunk.
pub fn read(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
{
read_data! {
endian: BIG, buf: b, size: 16, start: 0, data {
let index = u16[2];
let volume = u16[4];
}
}
read_data! {
endian: BIG, buf: b, size: 16, start: 0, data {
let index = u16[2];
let volume = u16[4];
}
}
Ok((SoundAmbi{index, volume}, 16))
Ok((SoundAmbi{index, volume}, 16))
}
/// An ambient sound definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SoundAmbi {
pub index: u16,
pub volume: u16,
pub index: u16,
pub volume: u16,
}
// EOF

View File

@ -5,34 +5,34 @@ use crate::{bin::OptU16, err::*, fixed::{Angle, Unit}};
/// Reads an `Attack` object.
pub fn read(b: &[u8]) -> ResultS<Attack>
{
read_data! {
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];
}
}
read_data! {
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})
Ok(Attack{ptype, rep, error, range, shape, ofs_x, ofs_y, ofs_z})
}
/// The definition of a monster's attack.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Attack {
pub ptype: OptU16,
pub rep: u16,
pub error: Angle,
pub range: Unit,
pub shape: u16,
pub ofs_x: Unit,
pub ofs_y: Unit,
pub ofs_z: Unit,
pub ptype: OptU16,
pub rep: u16,
pub error: Angle,
pub range: Unit,
pub shape: u16,
pub ofs_x: Unit,
pub ofs_y: Unit,
pub ofs_z: Unit,
}
// EOF

View File

@ -5,48 +5,48 @@ use crate::{err::*, fixed::{Angle, Fixed}};
/// Reads a `bonk` chunk.
pub fn read(b: &[u8]) -> ResultS<(SoundRand, usize)>
{
read_data! {
endian: BIG, buf: b, size: 32, start: 0, data {
let flags = u16[0] flag SoundRandFlags;
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];
}
}
read_data! {
endian: BIG, buf: b, size: 32, start: 0, data {
let flags = u16[0] flag SoundRandFlags;
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];
}
}
Ok((SoundRand{flags, index, vol_nrm, vol_dta, prd_nrm, prd_dta, yaw_nrm,
yaw_dta, pit_nrm, pit_dta}, 32))
Ok((SoundRand{flags, index, vol_nrm, vol_dta, prd_nrm, prd_dta, yaw_nrm,
yaw_dta, pit_nrm, pit_dta}, 32))
}
/// A randomly played sound definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SoundRand {
pub flags: SoundRandFlags,
pub index: u16,
pub vol_nrm: u16,
pub vol_dta: u16,
pub prd_nrm: u16,
pub prd_dta: u16,
pub yaw_nrm: Angle,
pub yaw_dta: Angle,
pub pit_nrm: Fixed,
pub pit_dta: Fixed,
pub flags: SoundRandFlags,
pub index: u16,
pub vol_nrm: u16,
pub vol_dta: u16,
pub prd_nrm: u16,
pub prd_dta: u16,
pub yaw_nrm: Angle,
pub yaw_dta: Angle,
pub pit_nrm: Fixed,
pub pit_dta: Fixed,
}
c_bitfield! {
/// Flags for `SoundRand`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct SoundRandFlags: u16 {
NO_DIRECTION = 0,
_2 = 1,
}
/// Flags for `SoundRand`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct SoundRandFlags: u16 {
NO_DIRECTION = 0,
_2 = 1,
}
}
// EOF

View File

@ -5,99 +5,99 @@ use crate::{err::*, fixed::Fixed};
/// Reads a `Damage` object.
pub fn read(b: &[u8]) -> ResultS<Damage>
{
read_data! {
endian: BIG, buf: b, size: 12, start: 0, data {
let dtype = u16[0] enum DamageType;
let flags = u16[2] flag DamageFlags;
let dmg_base = u16[4];
let dmg_rand = u16[6];
let scale = Fixed[8];
}
}
read_data! {
endian: BIG, buf: b, size: 12, start: 0, data {
let dtype = u16[0] enum DamageType;
let flags = u16[2] flag DamageFlags;
let dmg_base = u16[4];
let dmg_rand = u16[6];
let scale = Fixed[8];
}
}
Ok(Damage{dtype, flags, dmg_base, dmg_rand, scale})
Ok(Damage{dtype, flags, dmg_base, dmg_rand, scale})
}
/// A damage definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Damage {
pub dtype: DamageType,
pub flags: DamageFlags,
pub dmg_base: u16,
pub dmg_rand: u16,
pub scale: Fixed,
pub dtype: DamageType,
pub flags: DamageFlags,
pub dmg_base: u16,
pub dmg_rand: u16,
pub scale: Fixed,
}
c_bitfield! {
/// The composite type of damage taken by something.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct DamageTypeFlags: u32 {
EXPLOSION = 0,
ELECTRICAL_STAFF = 1,
PROJECTILE = 2,
ABSORBED = 3,
FLAME = 4,
HOUND_CLAWS = 5,
ALIEN_PROJECTILE = 6,
HULK_SLAP = 7,
COMPILER_BOLT = 8,
FUSION_BOLT = 9,
HUNTER_BOLT = 10,
FIST = 11,
TELEPORTER = 12,
DEFENDER = 13,
YETI_CLAWS = 14,
YETI_PROJECTILE = 15,
CRUSHING = 16,
LAVA = 17,
SUFFOCATION = 18,
GOO = 19,
ENERGY_DRAIN = 20,
OXYGEN_DRAIN = 21,
HUMMER_BOLT = 22,
SHOTGUN_PROJECTILE = 23,
}
/// The composite type of damage taken by something.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct DamageTypeFlags: u32 {
EXPLOSION = 0,
ELECTRICAL_STAFF = 1,
PROJECTILE = 2,
ABSORBED = 3,
FLAME = 4,
HOUND_CLAWS = 5,
ALIEN_PROJECTILE = 6,
HULK_SLAP = 7,
COMPILER_BOLT = 8,
FUSION_BOLT = 9,
HUNTER_BOLT = 10,
FIST = 11,
TELEPORTER = 12,
DEFENDER = 13,
YETI_CLAWS = 14,
YETI_PROJECTILE = 15,
CRUSHING = 16,
LAVA = 17,
SUFFOCATION = 18,
GOO = 19,
ENERGY_DRAIN = 20,
OXYGEN_DRAIN = 21,
HUMMER_BOLT = 22,
SHOTGUN_PROJECTILE = 23,
}
}
c_bitfield! {
/// Flags for `Damage`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct DamageFlags: u16 {
ALIEN = 0,
}
/// Flags for `Damage`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct DamageFlags: u16 {
ALIEN = 0,
}
}
c_enum! {
/// A named type of damage taken by something.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum DamageType: u16 {
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,
}
/// A named type of damage taken by something.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum DamageType: u16 {
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,
}
}
// EOF

View File

@ -7,187 +7,187 @@ use std::collections::BTreeMap;
/// Reads all chunks in an entry.
pub fn read(head: &head::Header, b: &[u8]) -> ResultS<EntryData>
{
let mut data = EntryData::default();
let mut data = EntryData::default();
let old = head.old_data();
let old = head.old_data();
let rd_cminf = if old {map::minf::read_old} else {map::minf::read};
let rd_csids = if old {map::sids::read_old} else {map::sids::read};
let rd_cpoly = if old {map::poly::read_old} else {map::poly::read};
let rd_clite = if old {map::lite::read_old} else {map::lite::read};
let rd_cminf = if old {map::minf::read_old} else {map::minf::read};
let rd_csids = if old {map::sids::read_old} else {map::sids::read};
let rd_cpoly = if old {map::poly::read_old} else {map::poly::read};
let rd_clite = if old {map::lite::read_old} else {map::lite::read};
let mut p = 0;
let mut p = 0;
while p < b.len() {
read_data! {
endian: BIG, buf: b, size: head.size_chunk(), start: p, data {
let iden = Ident[0];
let size = u32[8] usize;
}
}
while p < b.len() {
read_data! {
endian: BIG, buf: b, size: head.size_chunk(), start: p, data {
let iden = Ident[0];
let size = u32[8] usize;
}
}
let beg = p + head.size_chunk();
let end = beg + size;
let buf = ok!(b.get(beg..end), "not enough data")?;
let beg = p + head.size_chunk();
let end = beg + size;
let buf = ok!(b.get(beg..end), "not enough data")?;
match &iden.0 {
b"EPNT" => data.epnt = Some(rd_array(buf, map::epnt::read)?),
b"FXpx" => data.fxpx = Some(rd_array(buf, map::fxpx::read)?),
b"LINS" => data.lins = Some(rd_array(buf, map::lins::read)?),
b"LITE" => data.lite = Some(rd_array(buf, rd_clite)?),
b"MNpx" => data.mnpx = Some(rd_array(buf, map::mnpx::read)?),
b"Minf" => data.minf = Some(rd_cminf(buf)?),
b"NAME" => data.name = Some(rd_array(buf, map::name::read)?),
b"NOTE" => data.note = Some(rd_array(buf, map::note::read)?),
b"OBJS" => data.objs = Some(rd_array(buf, map::objs::read)?),
b"PICT" => data.pict = Some(pict::read(buf)?),
b"PNTS" => data.pnts = Some(rd_array(buf, map::pnts::read)?),
b"POLY" => data.poly = Some(rd_array(buf, rd_cpoly)?),
b"PRpx" => data.prpx = Some(rd_array(buf, map::prpx::read)?),
b"PXpx" => data.pxpx = Some(rd_array(buf, map::pxpx::read)?),
b"SIDS" => data.sids = Some(rd_array(buf, rd_csids)?),
b"WPpx" => data.wppx = Some(rd_array(buf, map::wppx::read)?),
b"ambi" => data.ambi = Some(rd_array(buf, map::ambi::read)?),
b"bonk" => data.bonk = Some(rd_array(buf, map::bonk::read)?),
b"iidx" => data.iidx = Some(rd_array(buf, map::iidx::read)?),
b"medi" => data.medi = Some(rd_array(buf, map::medi::read)?),
b"plac" => data.plac = Some(rd_array(buf, map::plac::read)?),
b"plat" => data.plat = Some(rd_array(buf, map::plat::read)?),
b"term" => data.term = Some(rd_array(buf, map::term::read)?),
_ => data.unkn.push((iden, buf.to_vec())),
}
match &iden.0 {
b"EPNT" => data.epnt = Some(rd_array(buf, map::epnt::read)?),
b"FXpx" => data.fxpx = Some(rd_array(buf, map::fxpx::read)?),
b"LINS" => data.lins = Some(rd_array(buf, map::lins::read)?),
b"LITE" => data.lite = Some(rd_array(buf, rd_clite)?),
b"MNpx" => data.mnpx = Some(rd_array(buf, map::mnpx::read)?),
b"Minf" => data.minf = Some(rd_cminf(buf)?),
b"NAME" => data.name = Some(rd_array(buf, map::name::read)?),
b"NOTE" => data.note = Some(rd_array(buf, map::note::read)?),
b"OBJS" => data.objs = Some(rd_array(buf, map::objs::read)?),
b"PICT" => data.pict = Some(pict::read(buf)?),
b"PNTS" => data.pnts = Some(rd_array(buf, map::pnts::read)?),
b"POLY" => data.poly = Some(rd_array(buf, rd_cpoly)?),
b"PRpx" => data.prpx = Some(rd_array(buf, map::prpx::read)?),
b"PXpx" => data.pxpx = Some(rd_array(buf, map::pxpx::read)?),
b"SIDS" => data.sids = Some(rd_array(buf, rd_csids)?),
b"WPpx" => data.wppx = Some(rd_array(buf, map::wppx::read)?),
b"ambi" => data.ambi = Some(rd_array(buf, map::ambi::read)?),
b"bonk" => data.bonk = Some(rd_array(buf, map::bonk::read)?),
b"iidx" => data.iidx = Some(rd_array(buf, map::iidx::read)?),
b"medi" => data.medi = Some(rd_array(buf, map::medi::read)?),
b"plac" => data.plac = Some(rd_array(buf, map::plac::read)?),
b"plat" => data.plat = Some(rd_array(buf, map::plat::read)?),
b"term" => data.term = Some(rd_array(buf, map::term::read)?),
_ => data.unkn.push((iden, buf.to_vec())),
}
p = end;
}
p = end;
}
Ok(data)
Ok(data)
}
/// Reads all of the data from an entry map.
pub fn read_all(head: &head::Header,
map: &entr::EntryMap<'_>) -> ResultS<EntryDataMap>
{
let mut data_map = EntryDataMap::new();
let mut data_map = EntryDataMap::new();
for (&index, entry) in map {
data_map.insert(index, read(head, entry.data)?);
}
for (&index, entry) in map {
data_map.insert(index, read(head, entry.data)?);
}
Ok(data_map)
Ok(data_map)
}
impl EntryData
{
pub fn get_type(&self) -> EntryType
{
if self.has_minf() {
EntryType::Map
} else if self.has_fxpx() ||
self.has_mnpx() ||
self.has_prpx() ||
self.has_pxpx() ||
self.has_wppx() {
EntryType::Physics
} else if self.has_pict() {
EntryType::Image
} else {
EntryType::Other
}
}
pub fn get_type(&self) -> EntryType
{
if self.has_minf() {
EntryType::Map
} else if self.has_fxpx() ||
self.has_mnpx() ||
self.has_prpx() ||
self.has_pxpx() ||
self.has_wppx() {
EntryType::Physics
} else if self.has_pict() {
EntryType::Image
} else {
EntryType::Other
}
}
pub fn has_epnt(&self) -> bool {self.epnt.is_some()}
pub fn has_fxpx(&self) -> bool {self.fxpx.is_some()}
pub fn has_lins(&self) -> bool {self.lins.is_some()}
pub fn has_lite(&self) -> bool {self.lite.is_some()}
pub fn has_mnpx(&self) -> bool {self.mnpx.is_some()}
pub fn has_minf(&self) -> bool {self.minf.is_some()}
pub fn has_name(&self) -> bool {self.name.is_some()}
pub fn has_note(&self) -> bool {self.note.is_some()}
pub fn has_objs(&self) -> bool {self.objs.is_some()}
pub fn has_pict(&self) -> bool {self.pict.is_some()}
pub fn has_pnts(&self) -> bool {self.pnts.is_some()}
pub fn has_poly(&self) -> bool {self.poly.is_some()}
pub fn has_prpx(&self) -> bool {self.prpx.is_some()}
pub fn has_pxpx(&self) -> bool {self.pxpx.is_some()}
pub fn has_sids(&self) -> bool {self.sids.is_some()}
pub fn has_wppx(&self) -> bool {self.wppx.is_some()}
pub fn has_ambi(&self) -> bool {self.ambi.is_some()}
pub fn has_bonk(&self) -> bool {self.bonk.is_some()}
pub fn has_iidx(&self) -> bool {self.iidx.is_some()}
pub fn has_medi(&self) -> bool {self.medi.is_some()}
pub fn has_plac(&self) -> bool {self.plac.is_some()}
pub fn has_plat(&self) -> bool {self.plat.is_some()}
pub fn has_term(&self) -> bool {self.term.is_some()}
pub fn has_epnt(&self) -> bool {self.epnt.is_some()}
pub fn has_fxpx(&self) -> bool {self.fxpx.is_some()}
pub fn has_lins(&self) -> bool {self.lins.is_some()}
pub fn has_lite(&self) -> bool {self.lite.is_some()}
pub fn has_mnpx(&self) -> bool {self.mnpx.is_some()}
pub fn has_minf(&self) -> bool {self.minf.is_some()}
pub fn has_name(&self) -> bool {self.name.is_some()}
pub fn has_note(&self) -> bool {self.note.is_some()}
pub fn has_objs(&self) -> bool {self.objs.is_some()}
pub fn has_pict(&self) -> bool {self.pict.is_some()}
pub fn has_pnts(&self) -> bool {self.pnts.is_some()}
pub fn has_poly(&self) -> bool {self.poly.is_some()}
pub fn has_prpx(&self) -> bool {self.prpx.is_some()}
pub fn has_pxpx(&self) -> bool {self.pxpx.is_some()}
pub fn has_sids(&self) -> bool {self.sids.is_some()}
pub fn has_wppx(&self) -> bool {self.wppx.is_some()}
pub fn has_ambi(&self) -> bool {self.ambi.is_some()}
pub fn has_bonk(&self) -> bool {self.bonk.is_some()}
pub fn has_iidx(&self) -> bool {self.iidx.is_some()}
pub fn has_medi(&self) -> bool {self.medi.is_some()}
pub fn has_plac(&self) -> bool {self.plac.is_some()}
pub fn has_plat(&self) -> bool {self.plat.is_some()}
pub fn has_term(&self) -> bool {self.term.is_some()}
pub fn num_unknown(&self) -> usize {self.unkn.len()}
pub fn num_unknown(&self) -> usize {self.unkn.len()}
pub fn len(&self) -> usize
{
self.num_unknown() +
usize::from(self.has_epnt()) +
usize::from(self.has_fxpx()) +
usize::from(self.has_lins()) +
usize::from(self.has_lite()) +
usize::from(self.has_mnpx()) +
usize::from(self.has_minf()) +
usize::from(self.has_name()) +
usize::from(self.has_note()) +
usize::from(self.has_objs()) +
usize::from(self.has_pict()) +
usize::from(self.has_pnts()) +
usize::from(self.has_poly()) +
usize::from(self.has_prpx()) +
usize::from(self.has_pxpx()) +
usize::from(self.has_sids()) +
usize::from(self.has_wppx()) +
usize::from(self.has_ambi()) +
usize::from(self.has_bonk()) +
usize::from(self.has_iidx()) +
usize::from(self.has_medi()) +
usize::from(self.has_plac()) +
usize::from(self.has_plat())
}
pub fn len(&self) -> usize
{
self.num_unknown() +
usize::from(self.has_epnt()) +
usize::from(self.has_fxpx()) +
usize::from(self.has_lins()) +
usize::from(self.has_lite()) +
usize::from(self.has_mnpx()) +
usize::from(self.has_minf()) +
usize::from(self.has_name()) +
usize::from(self.has_note()) +
usize::from(self.has_objs()) +
usize::from(self.has_pict()) +
usize::from(self.has_pnts()) +
usize::from(self.has_poly()) +
usize::from(self.has_prpx()) +
usize::from(self.has_pxpx()) +
usize::from(self.has_sids()) +
usize::from(self.has_wppx()) +
usize::from(self.has_ambi()) +
usize::from(self.has_bonk()) +
usize::from(self.has_iidx()) +
usize::from(self.has_medi()) +
usize::from(self.has_plac()) +
usize::from(self.has_plat())
}
pub fn is_empty(&self) -> bool {self.len() == 0}
pub fn is_empty(&self) -> bool {self.len() == 0}
}
/// The abstract type of an entry.
pub enum EntryType {
Other,
Map,
Image,
Physics,
Other,
Map,
Image,
Physics,
}
/// The loaded data of a Map file entry.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Default, Eq, PartialEq)]
pub struct EntryData {
/** `EPNT` chunk data. */ pub epnt: Option<Vec<map::epnt::Endpoint>>,
/** `FXpx` chunk data. */ pub fxpx: Option<Vec<map::fxpx::Effect>>,
/** `LINS` chunk data. */ pub lins: Option<Vec<map::lins::Line>>,
/** `LITE` chunk data. */ pub lite: Option<Vec<map::lite::Light>>,
/** `MNpx` chunk data. */ pub mnpx: Option<Vec<map::mnpx::Monster>>,
/** `Minf` chunk data. */ pub minf: Option<map::minf::Info>,
/** `NAME` chunk data. */ pub name: Option<Vec<String>>,
/** `NOTE` chunk data. */ pub note: Option<Vec<map::note::Note>>,
/** `OBJS` chunk data. */ pub objs: Option<Vec<map::objs::Object>>,
/** `PICT` chunk data. */ pub pict: Option<image::Image8>,
/** `PNTS` chunk data. */ pub pnts: Option<Vec<map::pnts::Point>>,
/** `POLY` chunk data. */ pub poly: Option<Vec<map::poly::Polygon>>,
/** `PRpx` chunk data. */ pub prpx: Option<Vec<map::prpx::Projectile>>,
/** `PXpx` chunk data. */ pub pxpx: Option<Vec<map::pxpx::Physics>>,
/** `SIDS` chunk data. */ pub sids: Option<Vec<map::sids::Side>>,
/** `WPpx` chunk data. */ pub wppx: Option<Vec<map::wppx::Weapon>>,
/** `ambi` chunk data. */ pub ambi: Option<Vec<map::ambi::SoundAmbi>>,
/** `bonk` chunk data. */ pub bonk: Option<Vec<map::bonk::SoundRand>>,
/** `iidx` chunk data. */ pub iidx: Option<Vec<u16>>,
/** `medi` chunk data. */ pub medi: Option<Vec<map::medi::Media>>,
/** `plac` chunk data. */ pub plac: Option<Vec<map::plac::ObjectFreq>>,
/** `plat` chunk data. */ pub plat: Option<Vec<map::plat::Platform>>,
/** `term` chunk data. */ pub term: Option<Vec<map::term::Terminal>>,
/** `EPNT` chunk data. */ pub epnt: Option<Vec<map::epnt::Endpoint>>,
/** `FXpx` chunk data. */ pub fxpx: Option<Vec<map::fxpx::Effect>>,
/** `LINS` chunk data. */ pub lins: Option<Vec<map::lins::Line>>,
/** `LITE` chunk data. */ pub lite: Option<Vec<map::lite::Light>>,
/** `MNpx` chunk data. */ pub mnpx: Option<Vec<map::mnpx::Monster>>,
/** `Minf` chunk data. */ pub minf: Option<map::minf::Info>,
/** `NAME` chunk data. */ pub name: Option<Vec<String>>,
/** `NOTE` chunk data. */ pub note: Option<Vec<map::note::Note>>,
/** `OBJS` chunk data. */ pub objs: Option<Vec<map::objs::Object>>,
/** `PICT` chunk data. */ pub pict: Option<image::Image8>,
/** `PNTS` chunk data. */ pub pnts: Option<Vec<map::pnts::Point>>,
/** `POLY` chunk data. */ pub poly: Option<Vec<map::poly::Polygon>>,
/** `PRpx` chunk data. */ pub prpx: Option<Vec<map::prpx::Projectile>>,
/** `PXpx` chunk data. */ pub pxpx: Option<Vec<map::pxpx::Physics>>,
/** `SIDS` chunk data. */ pub sids: Option<Vec<map::sids::Side>>,
/** `WPpx` chunk data. */ pub wppx: Option<Vec<map::wppx::Weapon>>,
/** `ambi` chunk data. */ pub ambi: Option<Vec<map::ambi::SoundAmbi>>,
/** `bonk` chunk data. */ pub bonk: Option<Vec<map::bonk::SoundRand>>,
/** `iidx` chunk data. */ pub iidx: Option<Vec<u16>>,
/** `medi` chunk data. */ pub medi: Option<Vec<map::medi::Media>>,
/** `plac` chunk data. */ pub plac: Option<Vec<map::plac::ObjectFreq>>,
/** `plat` chunk data. */ pub plat: Option<Vec<map::plat::Platform>>,
/** `term` chunk data. */ pub term: Option<Vec<map::term::Terminal>>,
pub unkn: Vec<(Ident, Vec<u8>)>,
pub unkn: Vec<(Ident, Vec<u8>)>,
}
/// A map of indexed entries.

View File

@ -7,61 +7,61 @@ use std::collections::BTreeMap;
/// Read an entry from a Map file.
pub fn read(map: &head::Map, i: usize) -> ResultS<(u16, Entry<'_>)>
{
let size = map.head().size_entry();
let b = map.dir();
let sta = size * i;
let size = map.head().size_entry();
let b = map.dir();
let sta = size * i;
read_data! {
endian: BIG, buf: b, size: size, start: sta, data {
let offset = u32[0] usize;
let dsize = u32[4] usize;
}
}
read_data! {
endian: BIG, buf: b, size: size, start: sta, data {
let offset = u32[0] usize;
let dsize = u32[4] usize;
}
}
let (index, app_data) = if !map.head().old_wad() {
read_data! {
endian: BIG, buf: b, size: size, start: sta, data {
let index = u16[8];
let app_data = u8[10; map.head().size_appl()];
}
}
(index, app_data)
} else {
(i as u16, &b[0..0])
};
let (index, app_data) = if !map.head().old_wad() {
read_data! {
endian: BIG, buf: b, size: size, start: sta, data {
let index = u16[8];
let app_data = u8[10; map.head().size_appl()];
}
}
(index, app_data)
} else {
(i as u16, &b[0..0])
};
let data = &map.data()[offset..offset + dsize];
let data = &map.data()[offset..offset + dsize];
Ok((index, Entry{data, app_data}))
Ok((index, Entry{data, app_data}))
}
/// Reads all entries in a Map file.
pub fn read_all(map: &head::Map) -> ResultS<EntryMap<'_>>
{
let mut entries = EntryMap::new();
let mut entries = EntryMap::new();
for i in 0..map.num_ent() {
let (index, entry) = read(map, i)?;
for i in 0..map.num_ent() {
let (index, entry) = read(map, i)?;
if entries.contains_key(&index) {
bail!("entry index already exists");
}
if entries.contains_key(&index) {
bail!("entry index already exists");
}
entries.insert(index, entry);
}
entries.insert(index, entry);
}
Ok(entries)
Ok(entries)
}
/// An entry containing chunked data and application-specific data.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Entry<'a> {
/// The data in this `Entry`.
pub data: &'a [u8],
/// The data in this `Entry`.
pub data: &'a [u8],
/// The application specific data for this Entry.
pub app_data: &'a [u8],
/// The application specific data for this Entry.
pub app_data: &'a [u8],
}
/// A map of indexed entries.

View File

@ -6,44 +6,44 @@ use crate::{err::*, fixed::Unit};
/// Reads an `EPNT` chunk.
pub fn read(b: &[u8]) -> ResultS<(Endpoint, usize)>
{
read_data! {
endian: BIG, buf: b, size: 16, start: 0, data {
let flags = u16[0] flag EndpointFlags;
let hei_hi = Unit[2];
let hei_lo = Unit[4];
let pos = pnts::read_o[6; 4];
let support = u16[10];
}
}
read_data! {
endian: BIG, buf: b, size: 16, start: 0, data {
let flags = u16[0] flag EndpointFlags;
let hei_hi = Unit[2];
let hei_lo = Unit[4];
let pos = pnts::read_o[6; 4];
let support = u16[10];
}
}
Ok((Endpoint{flags, hei_hi, hei_lo, pos, support}, 16))
Ok((Endpoint{flags, hei_hi, hei_lo, pos, support}, 16))
}
/// Converts a vector of `Endpoint`s to a vector of `Point`s.
pub fn to_pnts(v: &[Endpoint]) -> Vec<pnts::Point>
{
v.iter().map(|p| p.pos).collect()
v.iter().map(|p| p.pos).collect()
}
/// A pre-processed point in world-space.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Endpoint {
pub flags: EndpointFlags,
pub hei_hi: Unit,
pub hei_lo: Unit,
pub pos: pnts::Point,
pub support: u16,
pub flags: EndpointFlags,
pub hei_hi: Unit,
pub hei_lo: Unit,
pub pos: pnts::Point,
pub support: u16,
}
c_bitfield! {
/// Flags for `Endpoint`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EndpointFlags: u16 {
SOLID = 0,
SAME_HEIGHT = 1,
TRANSPARENT = 2,
}
/// Flags for `Endpoint`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EndpointFlags: u16 {
SOLID = 0,
SAME_HEIGHT = 1,
TRANSPARENT = 2,
}
}
// EOF

View File

@ -5,42 +5,42 @@ use crate::{bin::OptU16, err::*, fixed::Fixed};
/// Reads a `FXpx` chunk.
pub fn read(b: &[u8]) -> ResultS<(Effect, usize)>
{
read_data! {
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];
}
}
read_data! {
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];
}
}
Ok((Effect{collection, shape, pitch, flags, delay, delay_snd}, 14))
Ok((Effect{collection, shape, pitch, flags, delay, delay_snd}, 14))
}
/// An effect definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Effect {
pub collection: u16,
pub shape: u16,
pub pitch: Fixed,
pub flags: EffectFlags,
pub delay: OptU16,
pub delay_snd: OptU16,
pub collection: u16,
pub shape: u16,
pub pitch: Fixed,
pub flags: EffectFlags,
pub delay: OptU16,
pub delay_snd: OptU16,
}
c_bitfield! {
/// Flags for an effect.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EffectFlags: u16 {
END_ON_LOOP = 0,
END_ON_XFER_LOOP = 1,
SOUND_ONLY = 2,
MAKE_TWIN_VISIBLE = 3,
MEDIA_EFFECT = 4,
}
/// Flags for an effect.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EffectFlags: u16 {
END_ON_LOOP = 0,
END_ON_XFER_LOOP = 1,
SOUND_ONLY = 2,
MAKE_TWIN_VISIBLE = 3,
MEDIA_EFFECT = 4,
}
}
// EOF

View File

@ -6,145 +6,145 @@ use std::io::prelude::*;
/// Reads a Map file.
pub fn read(rd: &mut impl Read) -> ResultS<Map>
{
let mut data = Vec::new();
rd.read_to_end(&mut data)?;
let mut data = Vec::new();
rd.read_to_end(&mut data)?;
read_data! {
endian: BIG, buf: &data, size: 128, start: 0, data {
let ver_wad = u16[0] enum Ver;
let ver_data = u16[2];
let name = mac_roman_cstr[4; 64] no_try;
let dir_ofs = u32[72] usize;
let num_ent = u16[76] usize;
let size_appl = u16[78] usize;
let size_wcnk = u16[80] usize;
let size_went = u16[82] usize;
}
}
read_data! {
endian: BIG, buf: &data, size: 128, start: 0, data {
let ver_wad = u16[0] enum Ver;
let ver_data = u16[2];
let name = mac_roman_cstr[4; 64] no_try;
let dir_ofs = u32[72] usize;
let num_ent = u16[76] usize;
let size_appl = u16[78] usize;
let size_wcnk = u16[80] usize;
let size_went = u16[82] usize;
}
}
let head = Header::new(size_appl, ver_data, ver_wad, Some(name));
let head = Header::new(size_appl, ver_data, ver_wad, Some(name));
if !head.old_wad() && head.size_entry_base() != size_went {
bail!("invalid entry size");
}
if !head.old_wad() && head.size_entry_base() != size_went {
bail!("invalid entry size");
}
if !head.old_wad() && head.size_chunk() != size_wcnk {
bail!("invalid chunk size");
}
if !head.old_wad() && head.size_chunk() != size_wcnk {
bail!("invalid chunk size");
}
let map = Map{head, data, dir_ofs, num_ent};
let map = Map{head, data, dir_ofs, num_ent};
if map.dir_end() > map.data.len() {
bail!("not enough data in map file");
}
if map.dir_end() > map.data.len() {
bail!("not enough data in map file");
}
Ok(map)
Ok(map)
}
impl Header
{
/// Creates a new `Header`.
pub fn new(size_appl: usize,
ver_data: u16,
ver_wad: Ver,
name: Option<String>) -> Self
{
let name = name.unwrap_or_default();
Self{name, size_appl, ver_data, ver_wad}
}
/// Creates a new `Header`.
pub fn new(size_appl: usize,
ver_data: u16,
ver_wad: Ver,
name: Option<String>) -> Self
{
let name = name.unwrap_or_default();
Self{name, size_appl, ver_data, ver_wad}
}
/// Returns `true` if the data is in Marathon 1 format.
#[inline]
pub const fn old_data(&self) -> bool {self.ver_data() == 0}
/// Returns `true` if the data is in Marathon 1 format.
#[inline]
pub const fn old_data(&self) -> bool {self.ver_data() == 0}
/// Returns `true` if the Map file is in Marathon 1 format.
#[inline]
pub fn old_wad(&self) -> bool {self.ver_wad() == Ver::Base}
/// Returns `true` if the Map file is in Marathon 1 format.
#[inline]
pub fn old_wad(&self) -> bool {self.ver_wad() == Ver::Base}
/// The data version of this file.
#[inline]
pub const fn ver_data(&self) -> u16 {self.ver_data}
/// The data version of this file.
#[inline]
pub const fn ver_data(&self) -> u16 {self.ver_data}
/// The format version of this file.
#[inline]
pub const fn ver_wad(&self) -> Ver {self.ver_wad}
/// The format version of this file.
#[inline]
pub const fn ver_wad(&self) -> Ver {self.ver_wad}
/// The size of each `Entry`'s `appdata` field.
#[inline]
pub const fn size_appl(&self) -> usize {self.size_appl}
/// The size of each `Entry`'s `appdata` field.
#[inline]
pub const fn size_appl(&self) -> usize {self.size_appl}
/// The size of each `Entry`'s data.
#[inline]
pub fn size_entry_base(&self) -> usize {if self.old_wad() {8} else {10}}
/// The size of each `Entry`'s data.
#[inline]
pub fn size_entry_base(&self) -> usize {if self.old_wad() {8} else {10}}
/// The size of each `Entry`.
#[inline]
pub fn size_entry(&self) -> usize {self.size_entry_base() + self.size_appl()}
/// The size of each `Entry`.
#[inline]
pub fn size_entry(&self) -> usize {self.size_entry_base() + self.size_appl()}
/// The size of each chunk's header.
#[inline]
pub fn size_chunk(&self) -> usize {if self.old_wad() {12} else {16}}
/// The size of each chunk's header.
#[inline]
pub fn size_chunk(&self) -> usize {if self.old_wad() {12} else {16}}
}
impl Map
{
/// The header for this map.
#[inline]
pub const fn head(&self) -> &Header {&self.head}
/// The header for this map.
#[inline]
pub const fn head(&self) -> &Header {&self.head}
/// The data section of this map.
#[inline]
pub fn data(&self) -> &[u8] {&self.data[..]}
/// The data section of this map.
#[inline]
pub fn data(&self) -> &[u8] {&self.data[..]}
/// The directory section of this map.
#[inline]
pub fn dir(&self) -> &[u8] {&self.data[self.dir_beg()..self.dir_end()]}
/// The directory section of this map.
#[inline]
pub fn dir(&self) -> &[u8] {&self.data[self.dir_beg()..self.dir_end()]}
/// The number of entries in the directory.
#[inline]
pub const fn num_ent(&self) -> usize {self.num_ent}
/// The number of entries in the directory.
#[inline]
pub const fn num_ent(&self) -> usize {self.num_ent}
#[inline]
const fn dir_beg(&self) -> usize {self.dir_ofs}
#[inline]
const fn dir_beg(&self) -> usize {self.dir_ofs}
#[inline]
fn dir_end(&self) -> usize
{
self.dir_ofs + self.head.size_entry() * self.num_ent
}
#[inline]
fn dir_end(&self) -> usize
{
self.dir_ofs + self.head.size_entry() * self.num_ent
}
}
/// A Map header.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Header {
/// The original name of this file.
pub name: String,
/// The original name of this file.
pub name: String,
size_appl: usize,
ver_data: u16,
ver_wad: Ver,
size_appl: usize,
ver_data: u16,
ver_wad: Ver,
}
/// A Map file.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Map {
head: Header,
data: Vec<u8>,
dir_ofs: usize,
num_ent: usize,
head: Header,
data: Vec<u8>,
dir_ofs: usize,
num_ent: usize,
}
c_enum! {
/// The version of a Map file.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum Ver: u16 {
Base = 0,
Dir = 1,
Over = 2,
Inf = 4,
}
/// The version of a Map file.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum Ver: u16 {
Base = 0,
Dir = 1,
Over = 2,
Inf = 4,
}
}
// EOF

View File

@ -5,9 +5,9 @@ use crate::{bin::{check_data, u16b}, err::*};
/// Reads an `iidx` chunk.
pub fn read(b: &[u8]) -> ResultS<(u16, usize)>
{
check_data(b, 2)?;
check_data(b, 2)?;
Ok((u16b(b), 2))
Ok((u16b(b), 2))
}
// EOF

View File

@ -5,45 +5,45 @@ use crate::{bin::OptU16, err::*};
/// Reads a `LINS` chunk.
pub fn read(b: &[u8]) -> ResultS<(Line, usize)>
{
read_data! {
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];
}
}
read_data! {
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];
}
}
Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32))
Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32))
}
/// A line segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Line {
pub flags: LineFlags,
pub pnt_beg: u16,
pub pnt_end: u16,
pub side_fr: OptU16,
pub side_bk: OptU16,
pub poly_fr: OptU16,
pub poly_bk: OptU16,
pub flags: LineFlags,
pub pnt_beg: u16,
pub pnt_end: u16,
pub side_fr: OptU16,
pub side_bk: OptU16,
pub poly_fr: OptU16,
pub poly_bk: OptU16,
}
c_bitfield! {
/// Flags for `Line`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct LineFlags: u16 {
TRANS_SIDE = 9,
ELEV_VAR = 10,
ELEVATION = 11,
LANDSCAPE = 12,
TRANSPARENT = 13,
SOLID = 14,
}
/// Flags for `Line`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct LineFlags: u16 {
TRANS_SIDE = 9,
ELEV_VAR = 10,
ELEVATION = 11,
LANDSCAPE = 12,
TRANSPARENT = 13,
SOLID = 14,
}
}
// EOF

View File

@ -6,393 +6,393 @@ use crate::{err::*, fixed::Fixed};
/// Reads a `LITE` chunk.
pub fn read(b: &[u8]) -> ResultS<(Light, usize)>
{
read_data! {
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 = ltfn::read[6; 14];
let act_sec = ltfn::read[20; 14];
let act_mid = ltfn::read[34; 14];
let ina_pri = ltfn::read[48; 14];
let ina_sec = ltfn::read[62; 14];
let ina_mid = ltfn::read[76; 14];
let tag = u16[90];
}
}
read_data! {
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 = ltfn::read[6; 14];
let act_sec = ltfn::read[20; 14];
let act_mid = ltfn::read[34; 14];
let ina_pri = ltfn::read[48; 14];
let ina_sec = ltfn::read[62; 14];
let ina_mid = ltfn::read[76; 14];
let tag = u16[90];
}
}
Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec,
ina_mid, tag}, 100))
Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec,
ina_mid, tag}, 100))
}
/// Reads an old `LITE` chunk.
pub fn read_old(b: &[u8]) -> ResultS<(Light, usize)>
{
read_data! {
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];
}
}
read_data! {
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 {
bail!("bad old light type");
}
if OLD_LIGHT_DEFINITIONS.len() < ltype {
bail!("bad old light type");
}
let lite = &OLD_LIGHT_DEFINITIONS[ltype];
let on = mode == 0 || mode == 1;
let strobe = ltype == 3;
let flags = if on {lite.flags | LightFlags::INIT_ACTIVE} else {lite.flags};
let lite = &OLD_LIGHT_DEFINITIONS[ltype];
let on = mode == 0 || mode == 1;
let strobe = ltype == 3;
let flags = if on {lite.flags | LightFlags::INIT_ACTIVE} else {lite.flags};
// modify each old light function accordingly
let old_lfun = move |func: &ltfn::LightFunc| -> ltfn::LightFunc {
ltfn::LightFunc{ftype: func.ftype,
prd_nrm: if strobe {prd / 4 + 1} else {func.prd_nrm},
prd_dta: func.prd_dta,
val_nrm: if func.val_nrm > 0.into() {max} else {min},
val_dta: func.val_dta}
};
// modify each old light function accordingly
let old_lfun = move |func: &ltfn::LightFunc| -> ltfn::LightFunc {
ltfn::LightFunc{ftype: func.ftype,
prd_nrm: if strobe {prd / 4 + 1} else {func.prd_nrm},
prd_dta: func.prd_dta,
val_nrm: if func.val_nrm > 0.into() {max} else {min},
val_dta: func.val_dta}
};
Ok((Light{flags,
phase,
act_pri: old_lfun(&lite.act_pri),
act_sec: old_lfun(&lite.act_sec),
act_mid: old_lfun(&lite.act_mid),
ina_pri: old_lfun(&lite.ina_pri),
ina_sec: old_lfun(&lite.ina_sec),
ina_mid: old_lfun(&lite.ina_mid),
tag: 0,
..*lite}, 32))
Ok((Light{flags,
phase,
act_pri: old_lfun(&lite.act_pri),
act_sec: old_lfun(&lite.act_sec),
act_mid: old_lfun(&lite.act_mid),
ina_pri: old_lfun(&lite.ina_pri),
ina_sec: old_lfun(&lite.ina_sec),
ina_mid: old_lfun(&lite.ina_mid),
tag: 0,
..*lite}, 32))
}
/// A dynamic polygon light.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Light {
pub ltype: LightType,
pub flags: LightFlags,
pub phase: i16,
pub act_pri: ltfn::LightFunc,
pub act_sec: ltfn::LightFunc,
pub act_mid: ltfn::LightFunc,
pub ina_pri: ltfn::LightFunc,
pub ina_sec: ltfn::LightFunc,
pub ina_mid: ltfn::LightFunc,
pub tag: u16,
pub ltype: LightType,
pub flags: LightFlags,
pub phase: i16,
pub act_pri: ltfn::LightFunc,
pub act_sec: ltfn::LightFunc,
pub act_mid: ltfn::LightFunc,
pub ina_pri: ltfn::LightFunc,
pub ina_sec: ltfn::LightFunc,
pub ina_mid: ltfn::LightFunc,
pub tag: u16,
}
c_bitfield! {
/// Flags for `Light`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct LightFlags: u16 {
INIT_ACTIVE = 0,
SLAVE_VALUE = 1,
STATELESS = 2,
}
/// Flags for `Light`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct LightFlags: u16 {
INIT_ACTIVE = 0,
SLAVE_VALUE = 1,
STATELESS = 2,
}
}
c_enum! {
/// The type of a `Light`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum LightType: u16 {
Normal = 0,
Strobe = 1,
Media = 2,
}
/// The type of a `Light`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum LightType: u16 {
Normal = 0,
Strobe = 1,
Media = 2,
}
}
const OLD_LIGHT_DEFINITIONS: [Light; 8] = [
// Normal
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
tag: 0},
// Normal
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
tag: 0},
// Rheostat
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Rheostat
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Flourescent
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Fluorescent,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Flourescent
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Fluorescent,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Strobe
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Strobe
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Flicker
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Flicker,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Flicker
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Flicker,
prd_nrm: TICKS_PER_SECOND * 3,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Pulsate
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2 - 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2 - 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2 - 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Pulsate
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2 - 1,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2 - 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2 - 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Annoying
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
prd_nrm: 2,
prd_dta: 1,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Annoying
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
prd_nrm: 2,
prd_dta: 1,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
prd_nrm: 1,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
// Energy Efficient
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
];
// Energy Efficient
Light{ltype: LightType::Normal,
flags: LightFlags::SLAVE_VALUE,
phase: 0,
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(1),
val_dta: Fixed::from_int(0)},
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
prd_nrm: TICKS_PER_SECOND,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
prd_nrm: TICKS_PER_SECOND * 2,
prd_dta: 0,
val_nrm: Fixed::from_int(0),
val_dta: Fixed::from_int(0)},
tag: 0},
];
// EOF

View File

@ -5,53 +5,53 @@ use crate::{err::*, fixed::Fixed};
/// Reads a `LightFunc` object.
pub fn read(b: &[u8]) -> ResultS<LightFunc>
{
read_data! {
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];
}
}
read_data! {
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];
}
}
Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta})
Ok(LightFunc{ftype, prd_nrm, prd_dta, val_nrm, val_dta})
}
/// Writes a `LightFunc` object.
pub fn write(v: &LightFunc) -> Vec<u8>
{
let mut o = Vec::with_capacity(14);
o.extend(&(v.ftype as u16).to_be_bytes());
o.extend(&v.prd_nrm.to_be_bytes());
o.extend(&v.prd_dta.to_be_bytes());
o.extend(&v.val_nrm.to_be_bytes());
o.extend(&v.val_dta.to_be_bytes());
o
let mut o = Vec::with_capacity(14);
o.extend(&(v.ftype as u16).to_be_bytes());
o.extend(&v.prd_nrm.to_be_bytes());
o.extend(&v.prd_dta.to_be_bytes());
o.extend(&v.val_nrm.to_be_bytes());
o.extend(&v.val_dta.to_be_bytes());
o
}
/// A light function.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LightFunc {
pub ftype: LightFuncType,
pub prd_nrm: u16,
pub prd_dta: u16,
pub val_nrm: Fixed,
pub val_dta: Fixed,
pub ftype: LightFuncType,
pub prd_nrm: u16,
pub prd_dta: u16,
pub val_nrm: Fixed,
pub val_dta: Fixed,
}
c_enum! {
/// The type of function for a `LightFunc`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum LightFuncType: u16 {
Constant = 0,
Linear = 1,
Smooth = 2,
Flicker = 3,
Random = 4,
Fluorescent = 5,
}
/// The type of function for a `LightFunc`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum LightFuncType: u16 {
Constant = 0,
Linear = 1,
Smooth = 2,
Flicker = 3,
Random = 4,
Fluorescent = 5,
}
}
// EOF

View File

@ -9,63 +9,63 @@ use crate::{bin::OptU16,
/// Reads a `medi` chunk.
pub fn read(b: &[u8]) -> ResultS<(Media, usize)>
{
read_data! {
endian: BIG, buf: b, size: 32, start: 0, data {
let mtype = u16[0] enum MediaType;
let flags = u8[3] flag MediaFlags;
let control = u16[4];
let dir = Angle[6];
let mag = Unit[8];
let hei_lo = Unit[10];
let hei_hi = Unit[12];
let orig = pnts::read_o[14; 4];
let hei_nrm = Unit[18];
let min_lt = Fixed[20];
let texture = OptU16[24];
let xfer = u16[26] enum TransferMode;
}
}
read_data! {
endian: BIG, buf: b, size: 32, start: 0, data {
let mtype = u16[0] enum MediaType;
let flags = u8[3] flag MediaFlags;
let control = u16[4];
let dir = Angle[6];
let mag = Unit[8];
let hei_lo = Unit[10];
let hei_hi = Unit[12];
let orig = pnts::read_o[14; 4];
let hei_nrm = Unit[18];
let min_lt = Fixed[20];
let texture = OptU16[24];
let xfer = u16[26] enum TransferMode;
}
}
Ok((Media{mtype, flags, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm,
min_lt, texture, xfer}, 32))
Ok((Media{mtype, flags, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm,
min_lt, texture, xfer}, 32))
}
/// A media, as in a part of a polygon which goes up the middle of the wall.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Media {
pub mtype: MediaType,
pub flags: MediaFlags,
pub control: u16,
pub dir: Angle,
pub mag: Unit,
pub hei_lo: Unit,
pub hei_hi: Unit,
pub orig: pnts::Point,
pub hei_nrm: Unit,
pub min_lt: Fixed,
pub texture: OptU16,
pub xfer: TransferMode,
pub mtype: MediaType,
pub flags: MediaFlags,
pub control: u16,
pub dir: Angle,
pub mag: Unit,
pub hei_lo: Unit,
pub hei_hi: Unit,
pub orig: pnts::Point,
pub hei_nrm: Unit,
pub min_lt: Fixed,
pub texture: OptU16,
pub xfer: TransferMode,
}
c_enum! {
/// The liquid type of a `Media`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum MediaType: u16 {
Water = 0,
Lava = 1,
Goo = 2,
Sewage = 3,
Jjaro = 4,
}
/// The liquid type of a `Media`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum MediaType: u16 {
Water = 0,
Lava = 1,
Goo = 2,
Sewage = 3,
Jjaro = 4,
}
}
c_bitfield! {
/// Flags for `Media`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MediaFlags: u8 {
OBSTRUCT = 0,
}
/// Flags for `Media`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MediaFlags: u8 {
OBSTRUCT = 0,
}
}
// EOF

View File

@ -5,127 +5,127 @@ use crate::{err::*, text::*};
/// Reads a `Minf` chunk.
pub fn read(b: &[u8]) -> ResultS<Info>
{
read_data! {
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 MissionFlags;
let envi_flags = u16[8] flag EnvironmentFlags;
let level_name = mac_roman_cstr[18; 66] no_try;
let entr_flags = u32[84] flag EntryFlags;
}
}
read_data! {
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 MissionFlags;
let envi_flags = u16[8] flag EnvironmentFlags;
let level_name = mac_roman_cstr[18; 66] no_try;
let entr_flags = u32[84] flag EntryFlags;
}
}
Ok(Info{texture_id, physics_id, skypict_id, miss_flags, envi_flags,
entr_flags, level_name})
Ok(Info{texture_id, physics_id, skypict_id, miss_flags, envi_flags,
entr_flags, level_name})
}
/// Writes a `Minf` chunk.
pub fn write(v: &Info) -> Vec<u8>
{
let mut o = Vec::with_capacity(4);
o.extend(&v.texture_id.to_be_bytes());
o.extend(&v.physics_id.to_be_bytes());
o.extend(&v.skypict_id.to_be_bytes());
o.extend(&v.miss_flags.bits().to_be_bytes());
o.extend(&v.envi_flags.bits().to_be_bytes());
o.extend(&pad_zero(to_mac_roman(&v.level_name), 66));
o.extend(&v.entr_flags.bits().to_be_bytes());
o
let mut o = Vec::with_capacity(4);
o.extend(&v.texture_id.to_be_bytes());
o.extend(&v.physics_id.to_be_bytes());
o.extend(&v.skypict_id.to_be_bytes());
o.extend(&v.miss_flags.bits().to_be_bytes());
o.extend(&v.envi_flags.bits().to_be_bytes());
o.extend(&pad_zero(to_mac_roman(&v.level_name), 66));
o.extend(&v.entr_flags.bits().to_be_bytes());
o
}
/// Reads an old `Minf` chunk.
pub fn read_old(b: &[u8]) -> ResultS<Info>
{
let minf = read(b)?;
let minf = read(b)?;
let mut entr_flags = if minf.entr_flags.is_empty() {
EntryFlags::SOLO
} else {
minf.entr_flags
};
let mut entr_flags = if minf.entr_flags.is_empty() {
EntryFlags::SOLO
} else {
minf.entr_flags
};
if entr_flags.intersects(EntryFlags::SOLO | EntryFlags::CARNAGE) {
entr_flags.insert(EntryFlags::CO_OP)
}
if entr_flags.intersects(EntryFlags::SOLO | EntryFlags::CARNAGE) {
entr_flags.insert(EntryFlags::CO_OP)
}
Ok(Info{entr_flags, ..minf})
Ok(Info{entr_flags, ..minf})
}
impl Default for Info
{
fn default() -> Self
{
Self{texture_id: 0,
physics_id: 1,
skypict_id: 0,
miss_flags: MissionFlags::empty(),
envi_flags: EnvironmentFlags::empty(),
entr_flags: EntryFlags::SOLO,
level_name: "Map".to_string()}
}
fn default() -> Self
{
Self{texture_id: 0,
physics_id: 1,
skypict_id: 0,
miss_flags: MissionFlags::empty(),
envi_flags: EnvironmentFlags::empty(),
entr_flags: EntryFlags::SOLO,
level_name: "Map".to_string()}
}
}
/// Static map information.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Info {
pub texture_id: u16,
pub physics_id: u16,
pub skypict_id: u16,
pub miss_flags: MissionFlags,
pub envi_flags: EnvironmentFlags,
pub entr_flags: EntryFlags,
pub level_name: String,
pub texture_id: u16,
pub physics_id: u16,
pub skypict_id: u16,
pub miss_flags: MissionFlags,
pub envi_flags: EnvironmentFlags,
pub entr_flags: EntryFlags,
pub level_name: String,
}
c_bitfield! {
/// Static environment flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EnvironmentFlags: u16 {
VACUUM = 0,
MAGNETIC = 1,
REBELLION = 2,
LOW_GRAV = 3,
M1_GLUE = 4,
LAVA_FLOOR = 5,
REBELLION2 = 6,
MUSIC = 7,
TERM_PAUSE = 8,
M1_MONSTER = 9,
M1_WEPS = 10,
}
/// Static environment flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EnvironmentFlags: u16 {
VACUUM = 0,
MAGNETIC = 1,
REBELLION = 2,
LOW_GRAV = 3,
M1_GLUE = 4,
LAVA_FLOOR = 5,
REBELLION2 = 6,
MUSIC = 7,
TERM_PAUSE = 8,
M1_MONSTER = 9,
M1_WEPS = 10,
}
}
c_bitfield! {
/// Static entry point flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EntryFlags: u32 {
SOLO = 0,
CO_OP = 1,
CARNAGE = 2,
KTMWTB = 3,
KOTH = 4,
DEFENSE = 5,
RUGBY = 6,
CTF = 7,
}
/// Static entry point flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct EntryFlags: u32 {
SOLO = 0,
CO_OP = 1,
CARNAGE = 2,
KTMWTB = 3,
KOTH = 4,
DEFENSE = 5,
RUGBY = 6,
CTF = 7,
}
}
c_bitfield! {
/// Static mission flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MissionFlags: u16 {
EXTERMINATION = 0,
EXPLORATION = 1,
RETRIEVAL = 2,
REPAIR = 3,
RESCUE = 4,
M1_EXPLORATION = 5,
M1_RESCUE = 6,
M1_REPAIR = 7,
}
/// Static mission flags.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MissionFlags: u16 {
EXTERMINATION = 0,
EXPLORATION = 1,
RETRIEVAL = 2,
REPAIR = 3,
RESCUE = 4,
M1_EXPLORATION = 5,
M1_RESCUE = 6,
M1_REPAIR = 7,
}
}
// EOF

View File

@ -7,194 +7,194 @@ use super::{attk, damg};
/// Reads a `MNpx` chunk.
pub fn read(b: &[u8]) -> ResultS<(Monster, usize)>
{
read_data! {
endian: BIG, buf: b, size: 156, start: 0, data {
let collection = u16[0];
let vitality = u16[2];
let dty_immune = u32[4] flag damg::DamageTypeFlags;
let dty_weak = u32[8] flag damg::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 = damg::read[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 = attk::read[124; 16];
let atk_range = attk::read[140; 16];
}
}
read_data! {
endian: BIG, buf: b, size: 156, start: 0, data {
let collection = u16[0];
let vitality = u16[2];
let dty_immune = u32[4] flag damg::DamageTypeFlags;
let dty_weak = u32[8] flag damg::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 = damg::read[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 = attk::read[124; 16];
let atk_range = attk::read[140; 16];
}
}
// friend and enemy fields MUST truncate because the original source code
// used `-1` to represent "all classes" which should be invalid normally
// friend and enemy fields MUST truncate because the original source code
// used `-1` to represent "all classes" which should be invalid normally
let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
Ok((Monster{collection, vitality, dty_immune, dty_weak, flags, cls_self,
cls_friend, cls_enemy, snd_pitch, snd_see_enemy, snd_see_friend,
snd_seeclear, snd_kill, snd_apologize, snd_amicide, snd_flaming,
snd_active, snd_active_mask, typ_item, radius, height,
height_hover, ledge_min, ledge_max, ext_vel_scale, fxt_impact,
fxt_impact_melee, fxt_trail, half_fov_horz, half_fov_vert,
view_range, view_range_dark, intelligence, speed, gravity,
vel_terminal, door_try_mask, expl_radius, expl_damage, seq_hit,
seq_dying_hard, seq_dying_soft, seq_dead_hard, seq_dead_soft,
seq_standing, seq_moving, seq_tele_in, seq_tele_out,
atk_frequency, atk_melee, atk_range}, 156))
Ok((Monster{collection, vitality, dty_immune, dty_weak, flags, cls_self,
cls_friend, cls_enemy, snd_pitch, snd_see_enemy, snd_see_friend,
snd_seeclear, snd_kill, snd_apologize, snd_amicide, snd_flaming,
snd_active, snd_active_mask, typ_item, radius, height,
height_hover, ledge_min, ledge_max, ext_vel_scale, fxt_impact,
fxt_impact_melee, fxt_trail, half_fov_horz, half_fov_vert,
view_range, view_range_dark, intelligence, speed, gravity,
vel_terminal, door_try_mask, expl_radius, expl_damage, seq_hit,
seq_dying_hard, seq_dying_soft, seq_dead_hard, seq_dead_soft,
seq_standing, seq_moving, seq_tele_in, seq_tele_out,
atk_frequency, atk_melee, atk_range}, 156))
}
/// A monster definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Monster {
pub collection: u16,
pub vitality: u16,
pub dty_immune: damg::DamageTypeFlags,
pub dty_weak: damg::DamageTypeFlags,
pub flags: MonsterFlags,
pub cls_self: MonsterClass,
pub cls_friend: MonsterClass,
pub cls_enemy: MonsterClass,
pub snd_pitch: Fixed,
pub snd_see_enemy: OptU16,
pub snd_see_friend: OptU16,
pub snd_seeclear: OptU16,
pub snd_kill: OptU16,
pub snd_apologize: OptU16,
pub snd_amicide: OptU16,
pub snd_flaming: OptU16,
pub snd_active: OptU16,
pub snd_active_mask: u16,
pub typ_item: OptU16,
pub radius: Unit,
pub height: Unit,
pub height_hover: Unit,
pub ledge_min: Unit,
pub ledge_max: Unit,
pub ext_vel_scale: Fixed,
pub fxt_impact: OptU16,
pub fxt_impact_melee: OptU16,
pub fxt_trail: OptU16,
pub half_fov_horz: u16,
pub half_fov_vert: u16,
pub view_range: Unit,
pub view_range_dark: Unit,
pub intelligence: u16,
pub speed: u16,
pub gravity: u16,
pub vel_terminal: u16,
pub door_try_mask: u16,
pub expl_radius: OptU16,
pub expl_damage: damg::Damage,
pub seq_hit: OptU16,
pub seq_dying_hard: OptU16,
pub seq_dying_soft: OptU16,
pub seq_dead_hard: OptU16,
pub seq_dead_soft: OptU16,
pub seq_standing: u16,
pub seq_moving: u16,
pub seq_tele_in: OptU16,
pub seq_tele_out: OptU16,
pub atk_frequency: u16,
pub atk_melee: attk::Attack,
pub atk_range: attk::Attack,
pub collection: u16,
pub vitality: u16,
pub dty_immune: damg::DamageTypeFlags,
pub dty_weak: damg::DamageTypeFlags,
pub flags: MonsterFlags,
pub cls_self: MonsterClass,
pub cls_friend: MonsterClass,
pub cls_enemy: MonsterClass,
pub snd_pitch: Fixed,
pub snd_see_enemy: OptU16,
pub snd_see_friend: OptU16,
pub snd_seeclear: OptU16,
pub snd_kill: OptU16,
pub snd_apologize: OptU16,
pub snd_amicide: OptU16,
pub snd_flaming: OptU16,
pub snd_active: OptU16,
pub snd_active_mask: u16,
pub typ_item: OptU16,
pub radius: Unit,
pub height: Unit,
pub height_hover: Unit,
pub ledge_min: Unit,
pub ledge_max: Unit,
pub ext_vel_scale: Fixed,
pub fxt_impact: OptU16,
pub fxt_impact_melee: OptU16,
pub fxt_trail: OptU16,
pub half_fov_horz: u16,
pub half_fov_vert: u16,
pub view_range: Unit,
pub view_range_dark: Unit,
pub intelligence: u16,
pub speed: u16,
pub gravity: u16,
pub vel_terminal: u16,
pub door_try_mask: u16,
pub expl_radius: OptU16,
pub expl_damage: damg::Damage,
pub seq_hit: OptU16,
pub seq_dying_hard: OptU16,
pub seq_dying_soft: OptU16,
pub seq_dead_hard: OptU16,
pub seq_dead_soft: OptU16,
pub seq_standing: u16,
pub seq_moving: u16,
pub seq_tele_in: OptU16,
pub seq_tele_out: OptU16,
pub atk_frequency: u16,
pub atk_melee: attk::Attack,
pub atk_range: attk::Attack,
}
c_bitfield! {
/// Flags for a monster.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MonsterFlags: u32 {
IGNORE_LOS = 0,
FLYING = 1,
ALIEN = 2,
MAJOR = 3,
MINOR = 4,
NO_OMIT = 5,
FLOATS = 6,
NO_ATTACK = 7,
SNIPE = 8,
INVISIBLE = 9,
SUBTLY_INVISIBLE = 10,
KAMIKAZE = 11,
BERSERKER = 12,
ENLARGED = 13,
DELAYED_DEATH = 14,
FIRE_SYMMETRICAL = 15,
NUCLEAR_DEATH = 16,
NO_FIRE_BACKWARDS = 17,
CAN_DIE_IN_FLAMES = 18,
WAIT_FOR_GOOD_SHOT = 19,
TINY = 20,
FAST_ATTACK = 21,
LIKES_WATER = 22,
LIKES_SEWAGE = 23,
LIKES_LAVA = 24,
LIKES_GOO = 25,
TELE_UNDER_MEDIA = 26,
USE_RANDOM_WEAPON = 27,
}
/// Flags for a monster.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MonsterFlags: u32 {
IGNORE_LOS = 0,
FLYING = 1,
ALIEN = 2,
MAJOR = 3,
MINOR = 4,
NO_OMIT = 5,
FLOATS = 6,
NO_ATTACK = 7,
SNIPE = 8,
INVISIBLE = 9,
SUBTLY_INVISIBLE = 10,
KAMIKAZE = 11,
BERSERKER = 12,
ENLARGED = 13,
DELAYED_DEATH = 14,
FIRE_SYMMETRICAL = 15,
NUCLEAR_DEATH = 16,
NO_FIRE_BACKWARDS = 17,
CAN_DIE_IN_FLAMES = 18,
WAIT_FOR_GOOD_SHOT = 19,
TINY = 20,
FAST_ATTACK = 21,
LIKES_WATER = 22,
LIKES_SEWAGE = 23,
LIKES_LAVA = 24,
LIKES_GOO = 25,
TELE_UNDER_MEDIA = 26,
USE_RANDOM_WEAPON = 27,
}
}
c_bitfield! {
/// The composite type of a monster.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MonsterClass: u32 {
PLAYER = 0,
CIVILIAN = 1,
MADD = 2,
POSSESSED_HUMMER = 3,
DEFENDER = 4,
FIGHTER = 5,
TROOPER = 6,
HUNTER = 7,
ENFORCER = 8,
JUGGERNAUT = 9,
HUMMER = 10,
COMPILER = 11,
CYBORG = 12,
ASSIMILATED = 13,
TICK = 14,
YETI = 15,
}
/// The composite type of a monster.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct MonsterClass: u32 {
PLAYER = 0,
CIVILIAN = 1,
MADD = 2,
POSSESSED_HUMMER = 3,
DEFENDER = 4,
FIGHTER = 5,
TROOPER = 6,
HUNTER = 7,
ENFORCER = 8,
JUGGERNAUT = 9,
HUMMER = 10,
COMPILER = 11,
CYBORG = 12,
ASSIMILATED = 13,
TICK = 14,
YETI = 15,
}
}
// EOF

View File

@ -5,7 +5,7 @@ use crate::{err::*, text::mac_roman_cstr};
/// Reads a `NAME` chunk.
pub fn read(b: &[u8]) -> ResultS<(String, usize)>
{
Ok((mac_roman_cstr(b), b.len()))
Ok((mac_roman_cstr(b), b.len()))
}
// EOF

View File

@ -6,24 +6,24 @@ use crate::{err::*, text::*};
/// Reads a `NOTE` chunk.
pub fn read(b: &[u8]) -> ResultS<(Note, usize)>
{
read_data! {
endian: BIG, buf: b, size: 72, start: 0, data {
let pos = pnts::read_o[2; 4];
let poly = u16[6];
let text = mac_roman_cstr[8; 64] no_try;
}
}
read_data! {
endian: BIG, buf: b, size: 72, start: 0, data {
let pos = pnts::read_o[2; 4];
let poly = u16[6];
let text = mac_roman_cstr[8; 64] no_try;
}
}
Ok((Note{pos, poly, text}, 72))
Ok((Note{pos, poly, text}, 72))
}
/// Overhead map annotations.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Note {
pub pos: pnts::Point,
pub poly: u16,
pub text: String,
pub pos: pnts::Point,
pub poly: u16,
pub text: String,
}
// EOF

View File

@ -5,53 +5,53 @@ use crate::{err::*, fixed::{Angle, Unit}};
/// Reads an `OBJS` chunk.
pub fn read(b: &[u8]) -> ResultS<(Object, usize)>
{
read_data! {
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];
}
}
read_data! {
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;
let flags = flags & 0x0F_FF;
let bias = bias >> 12;
let flags = flag_ok!(ObjectFlags, flags)?;
let bias = flags & 0xF0_00;
let flags = flags & 0x0F_FF;
let bias = bias >> 12;
let flags = flag_ok!(ObjectFlags, flags)?;
Ok((Object{group, index, angle, poly, pos_x, pos_y, pos_z, flags, bias}, 16))
Ok((Object{group, index, angle, poly, pos_x, pos_y, pos_z, flags, bias}, 16))
}
/// An object in the world.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Object {
pub group: u16,
pub index: u16,
pub angle: Angle,
pub poly: u16,
pub pos_x: Unit,
pub pos_y: Unit,
pub pos_z: Unit,
pub flags: ObjectFlags,
pub bias: u16,
pub group: u16,
pub index: u16,
pub angle: Angle,
pub poly: u16,
pub pos_x: Unit,
pub pos_y: Unit,
pub pos_z: Unit,
pub flags: ObjectFlags,
pub bias: u16,
}
c_bitfield! {
/// Flags for `Object`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct ObjectFlags: u16 {
INVISIBLE = 0,
CEILING = 1,
BLIND = 2,
DEAF = 3,
FLOATING = 4,
NET_ONLY = 5,
}
/// Flags for `Object`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct ObjectFlags: u16 {
INVISIBLE = 0,
CEILING = 1,
BLIND = 2,
DEAF = 3,
FLOATING = 4,
NET_ONLY = 5,
}
}
// EOF

View File

@ -5,42 +5,42 @@ use crate::err::*;
/// Reads a `plac` chunk.
pub fn read(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
{
read_data! {
endian: BIG, buf: b, size: 12, start: 0, data {
let flags = u16[0] flag ObjectFreqFlags;
let cnt_ini = u16[2];
let cnt_min = u16[4];
let cnt_max = u16[6];
let cnt_rnd = u16[8];
let chance = u16[10];
}
}
read_data! {
endian: BIG, buf: b, size: 12, start: 0, data {
let flags = u16[0] flag ObjectFreqFlags;
let cnt_ini = u16[2];
let cnt_min = u16[4];
let cnt_max = u16[6];
let cnt_rnd = u16[8];
let chance = u16[10];
}
}
Ok((ObjectFreq{flags, cnt_ini, cnt_min, cnt_max, cnt_rnd, chance}, 12))
Ok((ObjectFreq{flags, cnt_ini, cnt_min, cnt_max, cnt_rnd, chance}, 12))
}
/// The difficulty definition for various object types.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ObjectFreq {
pub flags: ObjectFreqFlags,
pub cnt_ini: u16,
pub cnt_min: u16,
pub cnt_max: u16,
pub cnt_rnd: u16,
pub chance: u16,
pub flags: ObjectFreqFlags,
pub cnt_ini: u16,
pub cnt_min: u16,
pub cnt_max: u16,
pub cnt_rnd: u16,
pub chance: u16,
}
c_bitfield! {
/// Flags for `ObjectFreq`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct ObjectFreqFlags: u16 {
RANDOM_LOCATION = 0,
_3 = 3,
_4 = 4,
_5 = 5,
_6 = 6,
}
/// Flags for `ObjectFreq`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct ObjectFreqFlags: u16 {
RANDOM_LOCATION = 0,
_3 = 3,
_4 = 4,
_5 = 5,
_6 = 6,
}
}
// EOF

View File

@ -5,68 +5,68 @@ use crate::{err::*, fixed::Unit};
/// Reads a `plat` chunk.
pub fn read(b: &[u8]) -> ResultS<(Platform, usize)>
{
read_data! {
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];
}
}
read_data! {
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];
}
}
Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32))
Ok((Platform{ptype, speed, delay, hei_min, hei_max, flags, index, tag}, 32))
}
/// Extra information for polygons with platforms.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Platform {
pub ptype: u16,
pub speed: u16,
pub delay: u16,
pub hei_min: Unit,
pub hei_max: Unit,
pub flags: PlatformFlags,
pub index: u16,
pub tag: u16,
pub ptype: u16,
pub speed: u16,
pub delay: u16,
pub hei_min: Unit,
pub hei_max: Unit,
pub flags: PlatformFlags,
pub index: u16,
pub tag: u16,
}
c_bitfield! {
/// Flags for `Platform`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct PlatformFlags: u32 {
INIT_ACTIVE = 0,
INIT_EXTENDED = 1,
STOP_AT_EACH_LEVEL = 2,
STOP_AT_INIT_LEVEL = 3,
START_ADJ_ON_STOP = 4,
EXTENDS_FLOOR_TO_CEIL = 5,
COMES_FROM_FLOOR = 6,
COMES_FROM_CEIL = 7,
CAUSES_DAMAGE = 8,
NO_ACTIVATE_PARENT = 9,
ACTIVATES_ONCE = 10,
ACTIVATES_LIGHT = 11,
DEACTIVATES_LIGHT = 12,
PLAYER_CONTROLS = 13,
MONSTER_CONTROLS = 14,
REVERSE_ON_OBSTRUCT = 15,
NO_EXT_DEACTIVATION = 16,
USE_POLYGON_HEIGHTS = 17,
DELAYED_ACTIVATION = 18,
START_ADJ_ON_START = 19,
STOP_ADJ_ON_START = 20,
STOP_ADJ_ON_STOP = 21,
SLOW = 22,
START_AT_EACH_LEVEL = 23,
LOCKED = 24,
SECRET = 25,
DOOR = 26,
}
/// Flags for `Platform`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct PlatformFlags: u32 {
INIT_ACTIVE = 0,
INIT_EXTENDED = 1,
STOP_AT_EACH_LEVEL = 2,
STOP_AT_INIT_LEVEL = 3,
START_ADJ_ON_STOP = 4,
EXTENDS_FLOOR_TO_CEIL = 5,
COMES_FROM_FLOOR = 6,
COMES_FROM_CEIL = 7,
CAUSES_DAMAGE = 8,
NO_ACTIVATE_PARENT = 9,
ACTIVATES_ONCE = 10,
ACTIVATES_LIGHT = 11,
DEACTIVATES_LIGHT = 12,
PLAYER_CONTROLS = 13,
MONSTER_CONTROLS = 14,
REVERSE_ON_OBSTRUCT = 15,
NO_EXT_DEACTIVATION = 16,
USE_POLYGON_HEIGHTS = 17,
DELAYED_ACTIVATION = 18,
START_ADJ_ON_START = 19,
STOP_ADJ_ON_START = 20,
STOP_ADJ_ON_STOP = 21,
SLOW = 22,
START_AT_EACH_LEVEL = 23,
LOCKED = 24,
SECRET = 25,
DOOR = 26,
}
}
// EOF

View File

@ -5,23 +5,23 @@ use crate::{err::*, fixed::Unit};
/// Reads a `Point` object.
pub fn read_o(b: &[u8]) -> ResultS<Point>
{
read_data! {
endian: BIG, buf: b, size: 4, start: 0, data {
let x = Unit[0];
let y = Unit[2];
}
}
read_data! {
endian: BIG, buf: b, size: 4, start: 0, data {
let x = Unit[0];
let y = Unit[2];
}
}
Ok(Point{x, y})
Ok(Point{x, y})
}
/// Writes a `Point` object.
pub fn write_o(v: Point) -> Vec<u8>
{
let mut o = Vec::with_capacity(4);
o.extend(&v.x.to_be_bytes());
o.extend(&v.y.to_be_bytes());
o
let mut o = Vec::with_capacity(4);
o.extend(&v.x.to_be_bytes());
o.extend(&v.y.to_be_bytes());
o
}
/// Reads a `PNTS` chunk.
@ -31,8 +31,8 @@ pub fn read(b: &[u8]) -> ResultS<(Point, usize)> {Ok((read_o(b)?, 4))}
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct Point {
pub x: Unit,
pub y: Unit,
pub x: Unit,
pub y: Unit,
}
// EOF

View File

@ -6,185 +6,185 @@ use crate::{bin::OptU16, err::*, fixed::Unit, xfer::TransferMode};
/// Reads a polygon for either M1 or M2.
pub fn read_poly_inter(b: &[u8]) -> ResultS<Polygon>
{
read_data! {
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;
}
}
read_data! {
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;
}
}
Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr,
xfr_cei, ..Polygon::default()})
Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr,
xfr_cei, ..Polygon::default()})
}
/// Reads a `POLY` chunk.
pub fn read(b: &[u8]) -> ResultS<(Polygon, usize)>
{
read_data! {
endian: BIG, buf: b, size: 128, start: 0, data {
let ptype = u16[0];
let pdata = u16[4];
let ori_flr = pnts::read_o[108; 4];
let ori_cei = pnts::read_o[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];
}
}
read_data! {
endian: BIG, buf: b, size: 128, start: 0, data {
let ptype = u16[0];
let pdata = u16[4];
let ori_flr = pnts::read_o[108; 4];
let ori_cei = pnts::read_o[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)?;
let ptype = PolygonType::new(ptype, pdata)?;
let poly = read_poly_inter(b)?;
let ptype = PolygonType::new(ptype, pdata)?;
Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb,
snd_rnd, ..poly}, 128))
Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb,
snd_rnd, ..poly}, 128))
}
/// Reads an old `POLY` chunk.
pub fn read_old(b: &[u8]) -> ResultS<(Polygon, usize)>
{
read_data! {
endian: BIG, buf: b, size: 128, start: 0, data {
let ptype = u16[0];
let pdata = u16[4];
}
}
read_data! {
endian: BIG, buf: b, size: 128, start: 0, data {
let ptype = u16[0];
let pdata = u16[4];
}
}
let poly = read_poly_inter(b)?;
let ptype = PolygonType::new_old(ptype, pdata)?;
let poly = read_poly_inter(b)?;
let ptype = PolygonType::new_old(ptype, pdata)?;
Ok((Polygon{ptype, ..poly}, 128))
Ok((Polygon{ptype, ..poly}, 128))
}
impl PolygonType
{
/// Creates a `PolygonType` from a `n`/`pdata` pair.
pub fn new(n: u16, pdata: u16) -> Result<Self, ReprError>
{
match n {
0 => Ok(PolygonType::Normal),
1 => Ok(PolygonType::ImpassItem),
2 => Ok(PolygonType::ImpassMons),
3 => Ok(PolygonType::Hill),
4 => Ok(PolygonType::Base),
5 => Ok(PolygonType::Platform(pdata)),
6 => Ok(PolygonType::TrigLightOn(pdata)),
7 => Ok(PolygonType::TrigPlatOn(pdata)),
8 => Ok(PolygonType::TrigLightOff(pdata)),
9 => Ok(PolygonType::TrigPlatOff(pdata)),
10 => Ok(PolygonType::Teleporter(pdata)),
11 => Ok(PolygonType::ZoneBorder),
12 => Ok(PolygonType::Goal),
13 => Ok(PolygonType::TrigMonsVis),
14 => Ok(PolygonType::TrigMonsInv),
15 => Ok(PolygonType::TrigMonsDual),
16 => Ok(PolygonType::TrigItems),
17 => Ok(PolygonType::MustExplore),
18 => Ok(PolygonType::AutoExit),
19 => Ok(PolygonType::OuchMinor),
20 => Ok(PolygonType::OuchMajor),
21 => Ok(PolygonType::Glue),
22 => Ok(PolygonType::GlueTrigger(pdata)),
23 => Ok(PolygonType::GlueSuper),
n => Err(ReprError::new("PolygonType", n)),
}
}
/// Creates a `PolygonType` from a `n`/`pdata` pair.
pub fn new(n: u16, pdata: u16) -> Result<Self, ReprError>
{
match n {
0 => Ok(PolygonType::Normal),
1 => Ok(PolygonType::ImpassItem),
2 => Ok(PolygonType::ImpassMons),
3 => Ok(PolygonType::Hill),
4 => Ok(PolygonType::Base),
5 => Ok(PolygonType::Platform(pdata)),
6 => Ok(PolygonType::TrigLightOn(pdata)),
7 => Ok(PolygonType::TrigPlatOn(pdata)),
8 => Ok(PolygonType::TrigLightOff(pdata)),
9 => Ok(PolygonType::TrigPlatOff(pdata)),
10 => Ok(PolygonType::Teleporter(pdata)),
11 => Ok(PolygonType::ZoneBorder),
12 => Ok(PolygonType::Goal),
13 => Ok(PolygonType::TrigMonsVis),
14 => Ok(PolygonType::TrigMonsInv),
15 => Ok(PolygonType::TrigMonsDual),
16 => Ok(PolygonType::TrigItems),
17 => Ok(PolygonType::MustExplore),
18 => Ok(PolygonType::AutoExit),
19 => Ok(PolygonType::OuchMinor),
20 => Ok(PolygonType::OuchMajor),
21 => Ok(PolygonType::Glue),
22 => Ok(PolygonType::GlueTrigger(pdata)),
23 => Ok(PolygonType::GlueSuper),
n => Err(ReprError::new("PolygonType", n)),
}
}
/// Creates a `PolygonType` from a Marathon 1 compatible `n`/`pdata` pair.
fn new_old(n: u16, pdata: u16) -> Result<Self, ReprError>
{
match n {
0 => Ok(PolygonType::Normal),
1 => Ok(PolygonType::ImpassItem),
2 => Ok(PolygonType::ImpassMons),
3 => Ok(PolygonType::OuchMinor),
4 => Ok(PolygonType::OuchMajor),
5 => Ok(PolygonType::Platform(pdata)),
6 => Ok(PolygonType::TrigLightOn(pdata)),
7 => Ok(PolygonType::TrigPlatOn(pdata)),
8 => Ok(PolygonType::TrigLightOff(pdata)),
9 => Ok(PolygonType::TrigPlatOff(pdata)),
10 => Ok(PolygonType::Teleporter(pdata)),
11 => Ok(PolygonType::Glue),
12 => Ok(PolygonType::GlueTrigger(pdata)),
13 => Ok(PolygonType::GlueSuper),
14 => Ok(PolygonType::MustExplore),
15 => Ok(PolygonType::AutoExit),
n => Err(ReprError::new("PolygonType", n)),
}
}
/// Creates a `PolygonType` from a Marathon 1 compatible `n`/`pdata` pair.
fn new_old(n: u16, pdata: u16) -> Result<Self, ReprError>
{
match n {
0 => Ok(PolygonType::Normal),
1 => Ok(PolygonType::ImpassItem),
2 => Ok(PolygonType::ImpassMons),
3 => Ok(PolygonType::OuchMinor),
4 => Ok(PolygonType::OuchMajor),
5 => Ok(PolygonType::Platform(pdata)),
6 => Ok(PolygonType::TrigLightOn(pdata)),
7 => Ok(PolygonType::TrigPlatOn(pdata)),
8 => Ok(PolygonType::TrigLightOff(pdata)),
9 => Ok(PolygonType::TrigPlatOff(pdata)),
10 => Ok(PolygonType::Teleporter(pdata)),
11 => Ok(PolygonType::Glue),
12 => Ok(PolygonType::GlueTrigger(pdata)),
13 => Ok(PolygonType::GlueSuper),
14 => Ok(PolygonType::MustExplore),
15 => Ok(PolygonType::AutoExit),
n => Err(ReprError::new("PolygonType", n)),
}
}
}
impl Default for PolygonType
{
fn default() -> Self {PolygonType::Normal}
fn default() -> Self {PolygonType::Normal}
}
/// A polygon segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Polygon {
pub ptype: PolygonType,
pub tex_flr: OptU16,
pub tex_cei: OptU16,
pub hei_flr: Unit,
pub hei_cei: Unit,
pub lit_flr: u16,
pub lit_cei: u16,
pub xfr_flr: TransferMode,
pub xfr_cei: TransferMode,
pub ori_flr: pnts::Point,
pub ori_cei: pnts::Point,
pub med_ind: OptU16,
pub med_ctl: u16,
pub snd_ind: u16,
pub snd_amb: OptU16,
pub snd_rnd: OptU16,
pub ptype: PolygonType,
pub tex_flr: OptU16,
pub tex_cei: OptU16,
pub hei_flr: Unit,
pub hei_cei: Unit,
pub lit_flr: u16,
pub lit_cei: u16,
pub xfr_flr: TransferMode,
pub xfr_cei: TransferMode,
pub ori_flr: pnts::Point,
pub ori_cei: pnts::Point,
pub med_ind: OptU16,
pub med_ctl: u16,
pub snd_ind: u16,
pub snd_amb: OptU16,
pub snd_rnd: OptU16,
}
/// The action type of a `Polygon`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PolygonType {
Normal,
ImpassItem,
ImpassMons,
Hill,
Base,
Platform(u16),
TrigLightOn(u16),
TrigPlatOn(u16),
TrigLightOff(u16),
TrigPlatOff(u16),
Teleporter(u16),
ZoneBorder,
Goal,
TrigMonsVis,
TrigMonsInv,
TrigMonsDual,
TrigItems,
MustExplore,
AutoExit,
OuchMinor,
OuchMajor,
Glue,
GlueTrigger(u16),
GlueSuper,
Normal,
ImpassItem,
ImpassMons,
Hill,
Base,
Platform(u16),
TrigLightOn(u16),
TrigPlatOn(u16),
TrigLightOff(u16),
TrigPlatOff(u16),
Teleporter(u16),
ZoneBorder,
Goal,
TrigMonsVis,
TrigMonsInv,
TrigMonsDual,
TrigItems,
MustExplore,
AutoExit,
OuchMinor,
OuchMajor,
Glue,
GlueTrigger(u16),
GlueSuper,
}
c_bitfield! {
/// Flags for `Polygon`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct PolygonFlags: u16 {
DETACHED = 14,
}
/// Flags for `Polygon`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct PolygonFlags: u16 {
DETACHED = 14,
}
}
// EOF

View File

@ -7,83 +7,83 @@ use super::damg;
/// Reads a `PRpx` chunk.
pub fn read(b: &[u8]) -> ResultS<(Projectile, usize)>
{
read_data! {
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 = damg::read[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];
}
}
read_data! {
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 = damg::read[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];
}
}
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))
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))
}
/// A projectile definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Projectile {
pub collection: OptU16,
pub shape: u16,
pub fxt_explode: OptU16,
pub fxt_exp_media: OptU16,
pub fxt_trail: OptU16,
pub tic_trail: u16,
pub max_trail: OptU16,
pub typ_media: OptU16,
pub radius: Unit,
pub dmg_rad: Unit,
pub dmg_def: damg::Damage,
pub flags: ProjectileFlags,
pub speed: Unit,
pub range: Unit,
pub snd_pitch: Fixed,
pub snd_fly: OptU16,
pub snd_bounce: OptU16,
pub collection: OptU16,
pub shape: u16,
pub fxt_explode: OptU16,
pub fxt_exp_media: OptU16,
pub fxt_trail: OptU16,
pub tic_trail: u16,
pub max_trail: OptU16,
pub typ_media: OptU16,
pub radius: Unit,
pub dmg_rad: Unit,
pub dmg_def: damg::Damage,
pub flags: ProjectileFlags,
pub speed: Unit,
pub range: Unit,
pub snd_pitch: Fixed,
pub snd_fly: OptU16,
pub snd_bounce: OptU16,
}
c_bitfield! {
/// Flags for a projectile.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct ProjectileFlags: u32 {
GUIDED = 0,
STOP_ON_LOOP = 1,
PERSISTENT = 2,
ALIEN = 3,
GRAVITY = 4,
NO_HORZ_ERROR = 5,
NO_VERT_ERROR = 6,
TOGGLE_PANELS = 7,
POS_VERT_ERROR = 8,
MELEE = 9,
RIPPER = 10,
PASS_TRANS_RANDOM = 11,
PASS_TRANS_MORE = 12,
DOUBLE_GRAVITY = 13,
REBOUND_FLOOR = 14,
THROUGH_MEDIA = 15,
BECOME_ITEM = 16,
BLOODY = 17,
WANDER_HORZ = 18,
WANDER_VERT = 19,
USE_LOW_GRAV = 20,
PASS_MEDIA = 21,
}
/// Flags for a projectile.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct ProjectileFlags: u32 {
GUIDED = 0,
STOP_ON_LOOP = 1,
PERSISTENT = 2,
ALIEN = 3,
GRAVITY = 4,
NO_HORZ_ERROR = 5,
NO_VERT_ERROR = 6,
TOGGLE_PANELS = 7,
POS_VERT_ERROR = 8,
MELEE = 9,
RIPPER = 10,
PASS_TRANS_RANDOM = 11,
PASS_TRANS_MORE = 12,
DOUBLE_GRAVITY = 13,
REBOUND_FLOOR = 14,
THROUGH_MEDIA = 15,
BECOME_ITEM = 16,
BLOODY = 17,
WANDER_HORZ = 18,
WANDER_VERT = 19,
USE_LOW_GRAV = 20,
PASS_MEDIA = 21,
}
}
// EOF

View File

@ -5,73 +5,73 @@ use crate::{err::*, fixed::Fixed};
/// Reads a `PXpx` chunk.
pub fn read(b: &[u8]) -> ResultS<(Physics, usize)>
{
read_data! {
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];
}
}
read_data! {
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,
dec_nrm, dec_xng, ele_max, fng_max, fng_vel, ply_cam, ply_dhi,
ply_hcm, ply_hei, ply_rad, ply_spl, stp_amp, stp_dta, vel_ang,
vel_bkw, vel_fwd, vel_prp, vel_rec, vel_trm}, 104))
Ok((Physics{acc_ang, acc_cli, acc_grv, acc_nrm, dec_air, dec_ang, dec_ext,
dec_nrm, dec_xng, ele_max, fng_max, fng_vel, ply_cam, ply_dhi,
ply_hcm, ply_hei, ply_rad, ply_spl, stp_amp, stp_dta, vel_ang,
vel_bkw, vel_fwd, vel_prp, vel_rec, vel_trm}, 104))
}
/// Static physics information.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Physics {
pub acc_ang: Fixed,
pub acc_cli: Fixed,
pub acc_grv: Fixed,
pub acc_nrm: Fixed,
pub dec_air: Fixed,
pub dec_ang: Fixed,
pub dec_ext: Fixed,
pub dec_nrm: Fixed,
pub dec_xng: Fixed,
pub ele_max: Fixed,
pub fng_max: Fixed,
pub fng_vel: Fixed,
pub ply_cam: Fixed,
pub ply_dhi: Fixed,
pub ply_hcm: Fixed,
pub ply_hei: Fixed,
pub ply_rad: Fixed,
pub ply_spl: Fixed,
pub stp_amp: Fixed,
pub stp_dta: Fixed,
pub vel_ang: Fixed,
pub vel_bkw: Fixed,
pub vel_fwd: Fixed,
pub vel_prp: Fixed,
pub vel_rec: Fixed,
pub vel_trm: Fixed,
pub acc_ang: Fixed,
pub acc_cli: Fixed,
pub acc_grv: Fixed,
pub acc_nrm: Fixed,
pub dec_air: Fixed,
pub dec_ang: Fixed,
pub dec_ext: Fixed,
pub dec_nrm: Fixed,
pub dec_xng: Fixed,
pub ele_max: Fixed,
pub fng_max: Fixed,
pub fng_vel: Fixed,
pub ply_cam: Fixed,
pub ply_dhi: Fixed,
pub ply_hcm: Fixed,
pub ply_hei: Fixed,
pub ply_rad: Fixed,
pub ply_spl: Fixed,
pub stp_amp: Fixed,
pub stp_dta: Fixed,
pub vel_ang: Fixed,
pub vel_bkw: Fixed,
pub vel_fwd: Fixed,
pub vel_prp: Fixed,
pub vel_rec: Fixed,
pub vel_trm: Fixed,
}
// EOF

View File

@ -6,79 +6,79 @@ use crate::{bin::OptU16, err::*, fixed::Fixed, xfer::TransferMode};
/// Reads a `SIDS` chunk.
pub fn read(b: &[u8]) -> ResultS<(Side, usize)>
{
read_data! {
endian: BIG, buf: b, size: 64, start: 0, data {
let stype = u16[0] enum SideType;
let flags = u8[3] flag SideFlags;
let tex_pri = stex::read[4; 6];
let tex_sec = stex::read[10; 6];
let tex_tra = stex::read[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];
}
}
read_data! {
endian: BIG, buf: b, size: 64, start: 0, data {
let stype = u16[0] enum SideType;
let flags = u8[3] flag SideFlags;
let tex_pri = stex::read[4; 6];
let tex_sec = stex::read[10; 6];
let tex_tra = stex::read[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];
}
}
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
xfer_pri, xfer_sec, xfer_tra, shade}, 64))
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
xfer_pri, xfer_sec, xfer_tra, shade}, 64))
}
/// Reads an old `SIDS` chunk.
pub fn read_old(b: &[u8]) -> ResultS<(Side, usize)>
{
let (side, siz) = read(b)?;
let (side, siz) = read(b)?;
Ok((Side{tex_tra: stex::SideTex{tex_id: OptU16::none(), ..side.tex_tra},
shade: 0.into(),
flags: side.flags | SideFlags::ITEM_OPT,
..side}, siz))
Ok((Side{tex_tra: stex::SideTex{tex_id: OptU16::none(), ..side.tex_tra},
shade: 0.into(),
flags: side.flags | SideFlags::ITEM_OPT,
..side}, siz))
}
/// One side of a line segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Side {
pub stype: SideType,
pub flags: SideFlags,
pub tex_pri: stex::SideTex,
pub tex_sec: stex::SideTex,
pub tex_tra: stex::SideTex,
pub paneltyp: u16,
pub paneldat: i16,
pub xfer_pri: TransferMode,
pub xfer_sec: TransferMode,
pub xfer_tra: TransferMode,
pub shade: Fixed,
pub stype: SideType,
pub flags: SideFlags,
pub tex_pri: stex::SideTex,
pub tex_sec: stex::SideTex,
pub tex_tra: stex::SideTex,
pub paneltyp: u16,
pub paneldat: i16,
pub xfer_pri: TransferMode,
pub xfer_sec: TransferMode,
pub xfer_tra: TransferMode,
pub shade: Fixed,
}
c_bitfield! {
/// Flags for `Side`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct SideFlags: u8 {
STATUS = 0,
PANEL = 1,
REPAIR = 2,
ITEM_USE = 3,
LIGHTED = 4,
CAN_DESTROY = 5,
HIT_ONLY = 6,
ITEM_OPT = 7,
}
/// Flags for `Side`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct SideFlags: u8 {
STATUS = 0,
PANEL = 1,
REPAIR = 2,
ITEM_USE = 3,
LIGHTED = 4,
CAN_DESTROY = 5,
HIT_ONLY = 6,
ITEM_OPT = 7,
}
}
c_enum! {
/// The texture type of a `Side`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum SideType: u16 {
Full = 0,
High = 1,
Low = 2,
Composite = 3,
Split = 4,
}
/// The texture type of a `Side`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum SideType: u16 {
Full = 0,
High = 1,
Low = 2,
Composite = 3,
Split = 4,
}
}
// EOF

View File

@ -6,31 +6,31 @@ use super::pnts;
/// Reads a `SideTex` object.
pub fn read(b: &[u8]) -> ResultS<SideTex>
{
read_data! {
endian: BIG, buf: b, size: 6, start: 0, data {
let offs = pnts::read_o[0; 4];
let tex_id = OptU16[4];
}
}
read_data! {
endian: BIG, buf: b, size: 6, start: 0, data {
let offs = pnts::read_o[0; 4];
let tex_id = OptU16[4];
}
}
Ok(SideTex{offs, tex_id})
Ok(SideTex{offs, tex_id})
}
/// Writes a `SideTex` object.
pub fn write(v: &SideTex) -> Vec<u8>
{
let mut o = Vec::with_capacity(6);
o.extend(pnts::write_o(v.offs));
o.extend(&v.tex_id.to_be_bytes());
o
let mut o = Vec::with_capacity(6);
o.extend(pnts::write_o(v.offs));
o.extend(&v.tex_id.to_be_bytes());
o
}
/// The texture of a side segment.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SideTex {
pub offs: pnts::Point,
pub tex_id: OptU16,
pub offs: pnts::Point,
pub tex_id: OptU16,
}
// EOF

View File

@ -6,50 +6,50 @@ use crate::{bin, err::*, text};
/// Reads a `term` chunk.
pub fn read(b: &[u8]) -> ResultS<(Terminal, usize)>
{
read_data! {
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;
}
}
read_data! {
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 (i_grp, x) = bin::rd_array_num(&b[10..], group_n, trmg::read)?;
let (faces, y) = bin::rd_array_num(&b[10 + x..], face_n, trmf::read)?;
let (i_grp, x) = bin::rd_array_num(&b[10..], group_n, trmg::read)?;
let (faces, y) = bin::rd_array_num(&b[10 + x..], face_n, trmf::read)?;
let text = ok!(b.get(10 + x + y..end), "not enough data")?;
let text = if encoded != 0 {
text::fuck_string(text)
} else {
text.to_vec()
};
let text = ok!(b.get(10 + x + y..end), "not enough data")?;
let text = if encoded != 0 {
text::fuck_string(text)
} else {
text.to_vec()
};
let mut groups = Vec::with_capacity(group_n);
let mut groups = Vec::with_capacity(group_n);
for grp in &i_grp {
let flags = grp.flags;
let ttype = grp.ttype;
let lines = grp.lines;
let beg = grp.beg;
let len = grp.len;
let text = ok!(text.get(beg..beg + len), "bad offset")?;
let text = text::mac_roman_cstr(text);
for grp in &i_grp {
let flags = grp.flags;
let ttype = grp.ttype;
let lines = grp.lines;
let beg = grp.beg;
let len = grp.len;
let text = ok!(text.get(beg..beg + len), "bad offset")?;
let text = text::mac_roman_cstr(text);
groups.push(trmg::Group{flags, ttype, lines, text});
}
groups.push(trmg::Group{flags, ttype, lines, text});
}
Ok((Terminal{lines, groups, faces}, end))
Ok((Terminal{lines, groups, faces}, end))
}
/// A terminal definition, with collections of groups and faces.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Terminal {
pub lines: u16,
pub groups: Vec<trmg::Group>,
pub faces: Vec<trmf::Face>,
pub lines: u16,
pub groups: Vec<trmg::Group>,
pub faces: Vec<trmf::Face>,
}
// EOF

View File

@ -5,69 +5,69 @@ use crate::{bin::OptU16, err::*, fixed::Unit};
/// Reads a `Trigger` object.
pub fn read(b: &[u8]) -> ResultS<Trigger>
{
read_data! {
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];
}
}
read_data! {
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];
}
}
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})
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})
}
/// The definition of one of two triggers for a weapon.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Trigger {
pub burst: u16,
pub dx: i16,
pub dz: i16,
pub magazine: u16,
pub recoil: Unit,
pub snd_casing: OptU16,
pub snd_charge: OptU16,
pub snd_charged: OptU16,
pub snd_click: OptU16,
pub snd_fire: OptU16,
pub snd_reload: OptU16,
pub theta: u16,
pub tic_charge: u16,
pub tic_recover: u16,
pub tic_round: OptU16,
pub typ_ammo: OptU16,
pub typ_casing: CasingType,
pub typ_proj: u16,
pub burst: u16,
pub dx: i16,
pub dz: i16,
pub magazine: u16,
pub recoil: Unit,
pub snd_casing: OptU16,
pub snd_charge: OptU16,
pub snd_charged: OptU16,
pub snd_click: OptU16,
pub snd_fire: OptU16,
pub snd_reload: OptU16,
pub theta: u16,
pub tic_charge: u16,
pub tic_recover: u16,
pub tic_round: OptU16,
pub typ_ammo: OptU16,
pub typ_casing: CasingType,
pub typ_proj: u16,
}
c_enum! {
/// A bullet shell casing emitted by a weapon.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum CasingType: u16 {
Rifle = 0,
Pistol = 1,
PistolLeft = 2,
PistolRight = 3,
SMG = 4,
None = 0xFFFF,
}
/// A bullet shell casing emitted by a weapon.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum CasingType: u16 {
Rifle = 0,
Pistol = 1,
PistolLeft = 2,
PistolRight = 3,
SMG = 4,
None = 0xFFFF,
}
}
// EOF

View File

@ -5,24 +5,24 @@ use crate::err::*;
/// Reads a `Face`.
pub fn read(b: &[u8]) -> ResultS<(Face, usize)>
{
read_data! {
endian: BIG, buf: b, size: 6, start: 0, data {
let start = u16[0] usize;
let face = u16[2];
let color = u16[4];
}
}
read_data! {
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))
Ok((Face{start, face, color}, 6))
}
/// A text face.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Face {
pub start: usize,
pub face: u16,
pub color: u16,
pub start: usize,
pub face: u16,
pub color: u16,
}
// EOF

View File

@ -5,98 +5,98 @@ use crate::err::*;
/// Reads an `InterGroup`.
pub fn read(b: &[u8]) -> ResultS<(InterGroup, usize)>
{
read_data! {
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];
}
}
read_data! {
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 ttype = match ttype {
0 => GroupType::Logon(pdata),
1 => GroupType::Unfinished,
2 => GroupType::Success,
3 => GroupType::Failure,
4 => GroupType::Info,
5 => GroupType::End,
6 => GroupType::TeleInter(pdata),
7 => GroupType::TeleIntra(pdata),
8 => GroupType::Checkpoint(pdata),
9 => GroupType::Sound(pdata),
10 => GroupType::Movie(pdata),
11 => GroupType::Track(pdata),
12 => GroupType::Pict(pdata),
13 => GroupType::Logoff(pdata),
14 => GroupType::Camera(pdata),
15 => GroupType::Static(pdata),
16 => GroupType::Tag(pdata),
n => return Err(ReprError::new("GroupType", n).into()),
};
let ttype = match ttype {
0 => GroupType::Logon(pdata),
1 => GroupType::Unfinished,
2 => GroupType::Success,
3 => GroupType::Failure,
4 => GroupType::Info,
5 => GroupType::End,
6 => GroupType::TeleInter(pdata),
7 => GroupType::TeleIntra(pdata),
8 => GroupType::Checkpoint(pdata),
9 => GroupType::Sound(pdata),
10 => GroupType::Movie(pdata),
11 => GroupType::Track(pdata),
12 => GroupType::Pict(pdata),
13 => GroupType::Logoff(pdata),
14 => GroupType::Camera(pdata),
15 => GroupType::Static(pdata),
16 => GroupType::Tag(pdata),
n => return Err(ReprError::new("GroupType", n).into()),
};
Ok((InterGroup{flags, ttype, lines, beg, len}, 12))
Ok((InterGroup{flags, ttype, lines, beg, len}, 12))
}
impl Default for GroupType
{
fn default() -> Self {GroupType::Unfinished}
fn default() -> Self {GroupType::Unfinished}
}
/// Interim structure.
#[derive(Debug, Eq, PartialEq)]
pub struct InterGroup {
pub flags: GroupFlags,
pub ttype: GroupType,
pub lines: u16,
pub beg: usize,
pub len: usize,
pub flags: GroupFlags,
pub ttype: GroupType,
pub lines: u16,
pub beg: usize,
pub len: usize,
}
/// A terminal command grouping.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Group {
pub flags: GroupFlags,
pub ttype: GroupType,
pub lines: u16,
pub text: String,
pub flags: GroupFlags,
pub ttype: GroupType,
pub lines: u16,
pub text: String,
}
/// The command of a `Group`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GroupType {
Logon(u16),
Unfinished,
Success,
Failure,
Info,
End,
TeleInter(u16),
TeleIntra(u16),
Checkpoint(u16),
Sound(u16),
Movie(u16),
Track(u16),
Pict(u16),
Logoff(u16),
Camera(u16),
Static(u16),
Tag(u16),
Logon(u16),
Unfinished,
Success,
Failure,
Info,
End,
TeleInter(u16),
TeleIntra(u16),
Checkpoint(u16),
Sound(u16),
Movie(u16),
Track(u16),
Pict(u16),
Logoff(u16),
Camera(u16),
Static(u16),
Tag(u16),
}
c_bitfield! {
/// Flags for `Group`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct GroupFlags: u16 {
/// Draws the picture on the right.
DRAW_ON_RIGHT = 0,
/// Draws the picture in the center.
DRAW_CENTER = 1,
}
/// Flags for `Group`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct GroupFlags: u16 {
/// Draws the picture on the right.
DRAW_ON_RIGHT = 0,
/// Draws the picture in the center.
DRAW_CENTER = 1,
}
}
// EOF

View File

@ -7,102 +7,102 @@ use super::trig;
/// Reads a `WPpx` chunk.
pub fn read(b: &[u8]) -> ResultS<(Weapon, usize)>
{
read_data! {
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 = trig::read[62; 36];
let trig_sec = trig::read[98; 36];
}
}
read_data! {
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 = trig::read[62; 36];
let trig_sec = trig::read[98; 36];
}
}
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,
tic_powerup, tic_ready, trig_pri, trig_sec, typ_item,
typ_powerup, typ_weapon, wid_idle}, 134))
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,
tic_powerup, tic_ready, trig_pri, trig_sec, typ_item,
typ_powerup, typ_weapon, wid_idle}, 134))
}
/// A weapon definition.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Weapon {
pub amp_bob: Fixed,
pub amp_horz: Fixed,
pub collection: u16,
pub flags: WeaponFlags,
pub frm_charge: OptU16,
pub frm_charged: OptU16,
pub frm_firing: u16,
pub frm_idle: u16,
pub frm_reload: OptU16,
pub hei_idle: Fixed,
pub hei_kick: Fixed,
pub hei_reload: Fixed,
pub lit_decay: u16,
pub lit_value: Fixed,
pub tic_load_beg: u16,
pub tic_load_end: u16,
pub tic_load_mid: u16,
pub tic_powerup: u16,
pub tic_ready: u16,
pub trig_pri: trig::Trigger,
pub trig_sec: trig::Trigger,
pub typ_item: u16,
pub typ_powerup: OptU16,
pub typ_weapon: WeaponType,
pub wid_idle: Fixed,
pub amp_bob: Fixed,
pub amp_horz: Fixed,
pub collection: u16,
pub flags: WeaponFlags,
pub frm_charge: OptU16,
pub frm_charged: OptU16,
pub frm_firing: u16,
pub frm_idle: u16,
pub frm_reload: OptU16,
pub hei_idle: Fixed,
pub hei_kick: Fixed,
pub hei_reload: Fixed,
pub lit_decay: u16,
pub lit_value: Fixed,
pub tic_load_beg: u16,
pub tic_load_end: u16,
pub tic_load_mid: u16,
pub tic_powerup: u16,
pub tic_ready: u16,
pub trig_pri: trig::Trigger,
pub trig_sec: trig::Trigger,
pub typ_item: u16,
pub typ_powerup: OptU16,
pub typ_weapon: WeaponType,
pub wid_idle: Fixed,
}
c_bitfield! {
/// Flags for a weapon.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct WeaponFlags: u16 {
AUTOMATIC = 0,
REMOVE_AFTER_USE = 1,
INSTANT_CASING = 2,
OVERLOADS = 3,
RANDOM_AMMO = 4,
TEMPORARY_POWER = 5,
RELOAD_ONE_HAND = 6,
FIRE_OUT_OF_PHASE = 7,
FIRE_UNDER_MEDIA = 8,
TRIGGER_SAME_AMMO = 9,
SECONDARY_FLIP = 10,
}
/// Flags for a weapon.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct WeaponFlags: u16 {
AUTOMATIC = 0,
REMOVE_AFTER_USE = 1,
INSTANT_CASING = 2,
OVERLOADS = 3,
RANDOM_AMMO = 4,
TEMPORARY_POWER = 5,
RELOAD_ONE_HAND = 6,
FIRE_OUT_OF_PHASE = 7,
FIRE_UNDER_MEDIA = 8,
TRIGGER_SAME_AMMO = 9,
SECONDARY_FLIP = 10,
}
}
c_enum! {
/// The type of functionality a weapon provides.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum WeaponType: u16 {
Melee = 0,
Normal = 1,
DualFunc = 2,
DualPistol = 3,
Multipurpose = 4,
}
/// The type of functionality a weapon provides.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum WeaponType: u16 {
Melee = 0,
Normal = 1,
DualFunc = 2,
DualPistol = 3,
Multipurpose = 4,
}
}
// EOF

View File

@ -1,50 +1,50 @@
//! Meta-information of this crate.
macro_rules! meta_str {
($($(#[$outer:meta])* $name:ident = $e:expr;)*) => {
$($(#[$outer])* pub const fn $name() -> &'static str {$e})*
($($(#[$outer:meta])* $name:ident = $e:expr;)*) => {
$($(#[$outer])* pub const fn $name() -> &'static str {$e})*
pub mod ffi
{
$(
doc_comment! {
concat!("FFI variant of [`",
stringify!($name),
"`]\n\n[`",
stringify!($name),
"`]: ../fn.",
stringify!($name),
".html"),
pub const fn $name() -> crate::ffi::NT {c_str!($e)}
}
)*
}
}
pub mod ffi
{
$(
doc_comment! {
concat!("FFI variant of [`",
stringify!($name),
"`]\n\n[`",
stringify!($name),
"`]: ../fn.",
stringify!($name),
".html"),
pub const fn $name() -> crate::ffi::NT {c_str!($e)}
}
)*
}
}
}
meta_str! {
/// The authors of this crate, `:` separated.
authors = env!("CARGO_PKG_AUTHORS");
/// The description of this crate.
description = env!("CARGO_PKG_DESCRIPTION");
/// The home page of this crate.
homepage = env!("CARGO_PKG_HOMEPAGE");
/// The full license text of this crate.
license_text = include_str!("../LICENSE");
/// The name of this crate.
name = env!("CARGO_PKG_NAME");
/// The repository of this crate.
repository = env!("CARGO_PKG_REPOSITORY");
/// The full version of this crate.
version = env!("CARGO_PKG_VERSION");
/// The major version of this crate.
version_major = env!("CARGO_PKG_VERSION_MAJOR");
/// The minor version of this crate.
version_minor = env!("CARGO_PKG_VERSION_MINOR");
/// The patch version of this crate.
version_patch = env!("CARGO_PKG_VERSION_PATCH");
/// The pre-release version of this crate.
version_pre = env!("CARGO_PKG_VERSION_PRE");
/// The authors of this crate, `:` separated.
authors = env!("CARGO_PKG_AUTHORS");
/// The description of this crate.
description = env!("CARGO_PKG_DESCRIPTION");
/// The home page of this crate.
homepage = env!("CARGO_PKG_HOMEPAGE");
/// The full license text of this crate.
license_text = include_str!("../LICENSE");
/// The name of this crate.
name = env!("CARGO_PKG_NAME");
/// The repository of this crate.
repository = env!("CARGO_PKG_REPOSITORY");
/// The full version of this crate.
version = env!("CARGO_PKG_VERSION");
/// The major version of this crate.
version_major = env!("CARGO_PKG_VERSION_MAJOR");
/// The minor version of this crate.
version_minor = env!("CARGO_PKG_VERSION_MINOR");
/// The patch version of this crate.
version_patch = env!("CARGO_PKG_VERSION_PATCH");
/// The pre-release version of this crate.
version_pre = env!("CARGO_PKG_VERSION_PRE");
}
// EOF

View File

@ -14,40 +14,40 @@ pub fn read_coll_at_offset(b: &[u8],
ofs: u32,
len: usize) -> ResultS<Option<coll::Collection>>
{
if ofs != u32::max_value() {
let ofs = usize_from_u32(ofs);
let dat = ok!(b.get(ofs..ofs + len), "bad offset")?;
Ok(Some(coll::read(dat)?))
} else {
Ok(None)
}
if ofs != u32::max_value() {
let ofs = usize_from_u32(ofs);
let dat = ok!(b.get(ofs..ofs + len), "bad offset")?;
Ok(Some(coll::read(dat)?))
} else {
Ok(None)
}
}
/// Read all of the collections in a Shapes file.
pub fn read(fp: &mut impl Read) -> ResultS<Collections>
{
let mut b = Vec::new();
fp.read_to_end(&mut b)?;
let mut b = Vec::new();
fp.read_to_end(&mut b)?;
let mut collections = vec![(None, None); 32];
let mut collections = vec![(None, None); 32];
for (i, co) in collections.iter_mut().enumerate() {
read_data! {
endian: BIG, buf: &b, size: 32, start: i * 32, data {
let lo_ofs = u32[4];
let lo_len = u32[8] usize;
let hi_ofs = u32[12];
let hi_len = u32[16] usize;
}
}
for (i, co) in collections.iter_mut().enumerate() {
read_data! {
endian: BIG, buf: &b, size: 32, start: i * 32, data {
let lo_ofs = u32[4];
let lo_len = u32[8] usize;
let hi_ofs = u32[12];
let hi_len = u32[16] usize;
}
}
let lo = read_coll_at_offset(&b, lo_ofs, lo_len)?;
let hi = read_coll_at_offset(&b, hi_ofs, hi_len)?;
let lo = read_coll_at_offset(&b, lo_ofs, lo_len)?;
let hi = read_coll_at_offset(&b, hi_ofs, hi_len)?;
*co = (lo, hi);
}
*co = (lo, hi);
}
Ok(collections)
Ok(collections)
}
/// A collection, which may have low- and high-definition variations, or none.

View File

@ -6,135 +6,135 @@ use super::clut;
/// Reads a `Bitmap`.
pub fn read(b: &[u8]) -> ResultS<Bitmap>
{
read_data! {
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];
}
}
read_data! {
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 alpha = flags.contains(BmpFlags::TRANSPARENT);
let cmajr = flags.contains(BmpFlags::COLUMN_MAJOR);
let compr = compr == u16::max_value();
let alpha = flags.contains(BmpFlags::TRANSPARENT);
let cmajr = flags.contains(BmpFlags::COLUMN_MAJOR);
if depth != 8 {
bail!("invalid bit depth (should always be 8)");
}
if depth != 8 {
bail!("invalid bit depth (should always be 8)");
}
let mut bmp = Bitmap::new(width, height, alpha, cmajr);
let mut p = 30 + if cmajr {4 * width} else {4 * height};
let mut bmp = Bitmap::new(width, height, alpha, cmajr);
let mut p = 30 + if cmajr {4 * width} else {4 * height};
let scanlines = if cmajr {width} else {height};
let pitch = if cmajr {height} else {width};
let scanlines = if cmajr {width} else {height};
let pitch = if cmajr {height} else {width};
if compr {
// compressed scanlines (transparency RLE)
for _ in 0..scanlines {
read_data! {
endian: BIG, buf: b, size: 4, start: p, data {
let fst = u16[0] usize;
let lst = u16[2] usize;
}
}
if compr {
// compressed scanlines (transparency RLE)
for _ in 0..scanlines {
read_data! {
endian: BIG, buf: b, size: 4, start: p, data {
let fst = u16[0] usize;
let lst = u16[2] usize;
}
}
let end = lst - fst;
let end = lst - fst;
p += 4;
p += 4;
if lst < fst || fst > pitch || lst > pitch {
bail!("invalid compressed scanline");
}
if lst < fst || fst > pitch || lst > pitch {
bail!("invalid compressed scanline");
}
for _ in 0..fst {
bmp.cr.push(0);
}
for _ in 0..fst {
bmp.cr.push(0);
}
bmp.cr.extend(ok!(b.get(p..p + end), "not enough data")?);
bmp.cr.extend(ok!(b.get(p..p + end), "not enough data")?);
for _ in lst..pitch {
bmp.cr.push(0);
}
for _ in lst..pitch {
bmp.cr.push(0);
}
p += end;
}
} else {
// simple copy
bmp.cr.extend(ok!(b.get(p..p + width * height), "not enough data")?);
}
p += end;
}
} else {
// simple copy
bmp.cr.extend(ok!(b.get(p..p + width * height), "not enough data")?);
}
Ok(bmp)
Ok(bmp)
}
impl Bitmap
{
/// 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)}
}
/// 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)}
}
}
impl<'a, 'b> ImageShp<'a, 'b>
{
/// Creates an `ImageShp` with the given bitmap.
#[inline]
pub const fn new(bmp: &'a Bitmap, clut: &'b [clut::ColorShp]) -> Self
{
Self{bmp, clut}
}
/// Creates an `ImageShp` with the given bitmap.
#[inline]
pub const fn new(bmp: &'a Bitmap, clut: &'b [clut::ColorShp]) -> Self
{
Self{bmp, clut}
}
}
impl Image for ImageShp<'_, '_>
{
type Output = clut::ColorShp;
type Output = clut::ColorShp;
fn w(&self) -> usize {self.bmp.w}
fn h(&self) -> usize {self.bmp.h}
fn w(&self) -> usize {self.bmp.w}
fn h(&self) -> usize {self.bmp.h}
fn index(&self, x: usize, y: usize) -> &Self::Output
{
static TRANSLUCENT_COLOR: clut::ColorShp = clut::ColorShp::Translucent;
fn index(&self, x: usize, y: usize) -> &Self::Output
{
static TRANSLUCENT_COLOR: clut::ColorShp = clut::ColorShp::Translucent;
let cr = usize::from(if self.bmp.cmajr {
self.bmp.cr[y + x * self.bmp.h]
} else {
self.bmp.cr[x + y * self.bmp.w]
});
let cr = usize::from(if self.bmp.cmajr {
self.bmp.cr[y + x * self.bmp.h]
} else {
self.bmp.cr[x + y * self.bmp.w]
});
if self.bmp.alpha && cr == 0 {
&TRANSLUCENT_COLOR
} else {
self.clut.get(cr).unwrap_or(&TRANSLUCENT_COLOR)
}
}
if self.bmp.alpha && cr == 0 {
&TRANSLUCENT_COLOR
} else {
self.clut.get(cr).unwrap_or(&TRANSLUCENT_COLOR)
}
}
}
/// An unpacked Shape bitmap.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Bitmap {
w: usize,
h: usize,
cr: Vec<u8>,
alpha: bool,
cmajr: bool,
w: usize,
h: usize,
cr: Vec<u8>,
alpha: bool,
cmajr: bool,
}
/// An image from a Shape. This mainly just exists so that `Bitmap` can use the
/// `Image` trait.
#[derive(Debug, Eq, PartialEq)]
pub struct ImageShp<'a, 'b> {
bmp: &'a Bitmap,
clut: &'b [clut::ColorShp],
bmp: &'a Bitmap,
clut: &'b [clut::ColorShp],
}
c_bitfield! {
pub struct BmpFlags: u16 {
TRANSPARENT = 14,
COLUMN_MAJOR = 15,
}
pub struct BmpFlags: u16 {
TRANSPARENT = 14,
COLUMN_MAJOR = 15,
}
}
// EOF

View File

@ -5,27 +5,27 @@ use crate::{err::*, image::Color};
/// Reads a color from a color table into `clut`.
pub fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
{
read_data! {
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];
}
}
read_data! {
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")?;
let cr = ok!(clut.get_mut(usize::from(ind)), "bad index")?;
*cr = match flag {
128 => ColorShp::Lit {r, g, b},
0 => ColorShp::Opaque{r, g, b},
_ => {
return Err(err_msg("invalid flag in color"));
}
};
*cr = match flag {
128 => ColorShp::Lit {r, g, b},
0 => ColorShp::Opaque{r, g, b},
_ => {
return Err(err_msg("invalid flag in color"));
}
};
Ok(())
Ok(())
}
/// Reads color tables from `b`.
@ -34,78 +34,78 @@ pub fn read(b: &[u8],
tab_num: usize,
clr_num: usize) -> ResultS<Vec<Clut>>
{
let end = tab_num * clr_num * 8;
let end = tab_num * clr_num * 8;
let b = ok!(b.get(tab_ofs..tab_ofs + end), "bad offset")?;
let b = ok!(b.get(tab_ofs..tab_ofs + end), "bad offset")?;
let mut v = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
let mut p = 0;
let mut v = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
let mut p = 0;
for clut in v.iter_mut().take(tab_num) {
for _ in 0..clr_num {
read_color(ok!(b.get(p..p + 8), "not enough data")?, clut)?;
p += 8;
}
}
for clut in v.iter_mut().take(tab_num) {
for _ in 0..clr_num {
read_color(ok!(b.get(p..p + 8), "not enough data")?, clut)?;
p += 8;
}
}
Ok(v)
Ok(v)
}
impl Color for ColorShp
{
fn r(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{r, ..} |
ColorShp::Lit {r, ..} => r,
}
}
fn r(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{r, ..} |
ColorShp::Lit {r, ..} => r,
}
}
fn g(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{g, ..} |
ColorShp::Lit {g, ..} => g,
}
}
fn g(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{g, ..} |
ColorShp::Lit {g, ..} => g,
}
}
fn b(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{b, ..} |
ColorShp::Lit {b, ..} => b,
}
}
fn b(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{b, ..} |
ColorShp::Lit {b, ..} => b,
}
}
fn a(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{..} |
ColorShp::Lit {..} => u16::max_value(),
}
}
fn a(&self) -> u16
{
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{..} |
ColorShp::Lit {..} => u16::max_value(),
}
}
}
/// A color in a `Clut`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ColorShp {
/// A completely translucent color.
Translucent,
/// A completely translucent color.
Translucent,
/// An opaque color which may be shaded.
Opaque{/** The red component. */ r: u16,
/** The green component. */ g: u16,
/** The blue component. */ b: u16},
/// An opaque color which may be shaded.
Opaque{/** The red component. */ r: u16,
/** The green component. */ g: u16,
/** The blue component. */ b: u16},
/// An opaque color which may not be shaded.
Lit{/** The red component. */ r: u16,
/** The green component. */ g: u16,
/** The blue component. */ b: u16},
/// An opaque color which may not be shaded.
Lit{/** The red component. */ r: u16,
/** The green component. */ g: u16,
/** The blue component. */ b: u16},
}
/// A color collection.

View File

@ -6,63 +6,63 @@ use super::{bmap, clut, fram, sequ};
/// Reads a `Collection`.
pub fn read(b: &[u8]) -> ResultS<Collection>
{
read_data! {
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;
}
}
read_data! {
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;
}
}
if version != 3 {
bail!("invalid collection definition");
}
if version != 3 {
bail!("invalid collection definition");
}
let tabs = clut::read(b, tab_ofs, tab_num, clr_num)?;
let bmps = rd_ofstable(b, bmp_ofs, bmp_num, bmap::read)?;
let frms = rd_ofstable(b, frm_ofs, frm_num, fram::read)?;
let seqs = rd_ofstable(b, seq_ofs, seq_num, sequ::read)?;
let tabs = clut::read(b, tab_ofs, tab_num, clr_num)?;
let bmps = rd_ofstable(b, bmp_ofs, bmp_num, bmap::read)?;
let frms = rd_ofstable(b, frm_ofs, frm_num, fram::read)?;
let seqs = rd_ofstable(b, seq_ofs, seq_num, sequ::read)?;
Ok(Collection{ctyp: cl_type, tabs, bmps, frms, seqs})
Ok(Collection{ctyp: cl_type, tabs, bmps, frms, seqs})
}
/// A collection of color tables, bitmaps, frames and sequences.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Collection {
/// The type of collection this is.
pub ctyp: CollectionType,
/// The type of collection this is.
pub ctyp: CollectionType,
/// All of the color tables in this collection.
pub tabs: Vec<clut::Clut>,
/// All of the color tables in this collection.
pub tabs: Vec<clut::Clut>,
/// All of the bitmaps in this collection.
pub bmps: Vec<bmap::Bitmap>,
/// All of the bitmaps in this collection.
pub bmps: Vec<bmap::Bitmap>,
/// All of the frames in this collection.
pub frms: Vec<fram::Frame>,
/// All of the frames in this collection.
pub frms: Vec<fram::Frame>,
/// All of the sequences in this collection.
pub seqs: Vec<sequ::Sequence>,
/// All of the sequences in this collection.
pub seqs: Vec<sequ::Sequence>,
}
c_enum! {
/// The type of a collection.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum CollectionType: u16 {
Unused = 0,
Wall = 1,
Object = 2,
Interface = 3,
Scenery = 4,
}
/// The type of a collection.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum CollectionType: u16 {
Unused = 0,
Wall = 1,
Object = 2,
Interface = 3,
Scenery = 4,
}
}
// EOF

View File

@ -5,66 +5,66 @@ use crate::{err::*, fixed::*};
/// Reads a `Frame`.
pub fn read(b: &[u8]) -> ResultS<Frame>
{
read_data! {
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];
}
}
read_data! {
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];
}
}
Ok(Frame{flags, min_lt, bmp_ind, wrl_l, wrl_r, wrl_t, wrl_b, wrl_x, wrl_y})
Ok(Frame{flags, min_lt, bmp_ind, wrl_l, wrl_r, wrl_t, wrl_b, wrl_x, wrl_y})
}
/// A frame, also known as a low level shape.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Frame {
/// The flags for this frame.
pub flags: FrameFlags,
/// The flags for this frame.
pub flags: FrameFlags,
/// The minimum light level for this frame.
pub min_lt: Fixed,
/// The minimum light level for this frame.
pub min_lt: Fixed,
/// The index of the bitmap this frame uses.
pub bmp_ind: usize,
/// The index of the bitmap this frame uses.
pub bmp_ind: usize,
/// The left translation for this frame.
pub wrl_l: Unit,
/// The left translation for this frame.
pub wrl_l: Unit,
/// The right translation for this frame.
pub wrl_r: Unit,
/// The right translation for this frame.
pub wrl_r: Unit,
/// The top translation for this frame.
pub wrl_t: Unit,
/// The top translation for this frame.
pub wrl_t: Unit,
/// The bottom translation for this frame.
pub wrl_b: Unit,
/// The bottom translation for this frame.
pub wrl_b: Unit,
/// The X translation for this frame.
pub wrl_x: Unit,
/// The X translation for this frame.
pub wrl_x: Unit,
/// The Y translation for this frame.
pub wrl_y: Unit,
/// The Y translation for this frame.
pub wrl_y: Unit,
}
c_bitfield! {
/// Flags for `Frame`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct FrameFlags: u16 {
/// The player's torso will obscure the player's legs.
OBSCURE = 13,
/// The bitmap will be flipped on the vertical axis.
FLIP_Y = 14,
/// The bitmap will be flipped on the horizontal axis.
FLIP_X = 15,
}
/// Flags for `Frame`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct FrameFlags: u16 {
/// The player's torso will obscure the player's legs.
OBSCURE = 13,
/// The bitmap will be flipped on the vertical axis.
FLIP_Y = 14,
/// The bitmap will be flipped on the horizontal axis.
FLIP_X = 15,
}
}
// EOF

View File

@ -7,80 +7,80 @@ use crate::{bin::OptU16, err::*,
/// Reads a `Sequence`.
pub fn read(b: &[u8]) -> ResultS<Sequence>
{
read_data! {
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];
}
}
read_data! {
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 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})
Ok(Sequence{name, v_type, frames, ticks, key, xfer, xfer_pd, snd_beg,
snd_key, snd_end, loop_f})
}
/// A sequence, also known as a high level shape.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Sequence {
/// The display name for this sequence.
pub name: String,
/// The display name for this sequence.
pub name: String,
/// The view type for each frame in this sequence.
pub v_type: ViewType,
/// The view type for each frame in this sequence.
pub v_type: ViewType,
/// The number of frames in this sequence.
pub frames: u16,
/// The number of frames in this sequence.
pub frames: u16,
/// The number of ticks each frame in this sequence takes.
pub ticks: u16,
/// The number of ticks each frame in this sequence takes.
pub ticks: u16,
/// The key frame index for this sequence.
pub key: u16,
/// The key frame index for this sequence.
pub key: u16,
/// The transfer mode to play over this sequence.
pub xfer: TransferMode,
/// The transfer mode to play over this sequence.
pub xfer: TransferMode,
/// The period in game ticks the transfer mode plays over.
pub xfer_pd: u16,
/// The period in game ticks the transfer mode plays over.
pub xfer_pd: u16,
/// The sound to play at the beginning of this sequence.
pub snd_beg: OptU16,
/// The sound to play at the beginning of this sequence.
pub snd_beg: OptU16,
/// The sound to play at the key frame of this sequence.
pub snd_key: OptU16,
/// The sound to play at the key frame of this sequence.
pub snd_key: OptU16,
/// The sound to play at the end of this sequence.
pub snd_end: OptU16,
/// The sound to play at the end of this sequence.
pub snd_end: OptU16,
/// Which frame to loop on.
pub loop_f: u16,
/// Which frame to loop on.
pub loop_f: u16,
}
c_enum! {
/// The type of or number of views for a sequence.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum ViewType: u16 {
Anim = 1,
Anim8from2 = 2,
Anim4from3 = 3,
Anim4 = 4,
Anim8from5 = 5,
Anim8 = 8,
Anim5from3 = 9,
Still = 10,
Anim5 = 11,
}
/// The type of or number of views for a sequence.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum ViewType: u16 {
Anim = 1,
Anim8from2 = 2,
Anim4from3 = 3,
Anim4 = 4,
Anim8from5 = 5,
Anim8 = 8,
Anim5from3 = 9,
Still = 10,
Anim5 = 11,
}
}
// EOF

View File

@ -9,43 +9,43 @@ use std::{collections::BTreeMap, io::prelude::*};
/// Reads all sounds from a Sound file.
pub fn read(fp: &mut impl Read) -> ResultS<Vec<SoundTable>>
{
let mut b = Vec::new();
fp.read_to_end(&mut b)?;
let mut b = Vec::new();
fp.read_to_end(&mut b)?;
read_data! {
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;
}
}
read_data! {
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" {
bail!("bad sound header");
}
if version != 1 || magic != b"snd2" {
bail!("bad sound header");
}
let mut sc = Vec::with_capacity(src_num);
let mut sc = Vec::with_capacity(src_num);
for i in 0..src_num {
let p = 260 + i * 64;
for i in 0..src_num {
let p = 260 + i * 64;
let mut st = SoundTable::new();
let mut st = SoundTable::new();
for _ in 0..snd_num {
if let Some((ofs, idx, mut def)) = defs::read(&b[p..p + 64])? {
for &ofs in &ofs {
def.sounds.push(snds::read(&b[ofs..])?);
}
for _ in 0..snd_num {
if let Some((ofs, idx, mut def)) = defs::read(&b[p..p + 64])? {
for &ofs in &ofs {
def.sounds.push(snds::read(&b[ofs..])?);
}
st.insert(idx, def);
}
}
st.insert(idx, def);
}
}
sc.push(st);
}
sc.push(st);
}
Ok(sc)
Ok(sc)
}
/// A table of sound definitions.

View File

@ -5,92 +5,92 @@ use crate::{bin::{u32b, usize_from_u32}, err::*, fixed::*, sound::Sound16};
/// Reads a sound definition.
pub fn read(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
{
read_data! {
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;
}
}
read_data! {
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;
}
}
if index == u16::max_value() {
return Ok(None);
}
if index == u16::max_value() {
return Ok(None);
}
if n_sounds > 5 {
bail!("too many sounds");
}
if n_sounds > 5 {
bail!("too many sounds");
}
let mut ofs = Vec::with_capacity(n_sounds);
let mut p = 36;
let mut ofs = Vec::with_capacity(n_sounds);
let mut p = 36;
for _ in 0..n_sounds {
ofs.push(grp_ofs + usize_from_u32(u32b(&b[p..])));
p += 4;
}
for _ in 0..n_sounds {
ofs.push(grp_ofs + usize_from_u32(u32b(&b[p..])));
p += 4;
}
let sounds = Vec::with_capacity(n_sounds);
let sounds = Vec::with_capacity(n_sounds);
Ok(Some((ofs, index,
SoundDef{volume, flags, chance, pitch_lo, pitch_hi, sounds})))
Ok(Some((ofs, index,
SoundDef{volume, flags, chance, pitch_lo, pitch_hi, sounds})))
}
/// A sound definition containing one, many or no sounds.
#[derive(Debug, Eq, PartialEq)]
pub struct SoundDef {
/// The volume type for this sound.
pub volume: Volume,
/// The volume type for this sound.
pub volume: Volume,
/// The flags for this sound.
pub flags: SoundFlags,
/// The flags for this sound.
pub flags: SoundFlags,
/// The chance out of `u16::max_value()` that this sound will not play.
pub chance: u16,
/// The chance out of `u16::max_value()` that this sound will not play.
pub chance: u16,
/// The low random pitch bound.
pub pitch_lo: Fixed,
/// The low random pitch bound.
pub pitch_lo: Fixed,
/// The high random pitch bound.
pub pitch_hi: Fixed,
/// The high random pitch bound.
pub pitch_hi: Fixed,
/// All of the sounds in this collection.
pub sounds: Vec<Sound16>,
/// All of the sounds in this collection.
pub sounds: Vec<Sound16>,
}
c_bitfield! {
/// Flags for `SoundDef`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct SoundFlags: u16 {
/// The sound will not restart when trying to play over itself.
NO_RESTART = 0,
/// The sound will not switch channels when trying to play over itself.
NO_CHANNEL_SWITCH = 1,
/// The pitch variance will be halved.
LESS_PITCH_CHANGE = 2,
/// The pitch variance will be nullified.
NO_PITCH_CHANGE = 3,
/// The sound will play even when completely obstructed by walls.
NO_OBSTRUCTION = 4,
/// The sound will play even when completely obstructed by media.
NO_MEDIA_OBSTRUCT = 5,
/// The sound will have special stereo effects.
AMBIENT = 6,
}
/// Flags for `SoundDef`.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub struct SoundFlags: u16 {
/// The sound will not restart when trying to play over itself.
NO_RESTART = 0,
/// The sound will not switch channels when trying to play over itself.
NO_CHANNEL_SWITCH = 1,
/// The pitch variance will be halved.
LESS_PITCH_CHANGE = 2,
/// The pitch variance will be nullified.
NO_PITCH_CHANGE = 3,
/// The sound will play even when completely obstructed by walls.
NO_OBSTRUCTION = 4,
/// The sound will play even when completely obstructed by media.
NO_MEDIA_OBSTRUCT = 5,
/// The sound will have special stereo effects.
AMBIENT = 6,
}
}
c_enum! {
/// The type of volume this sound has.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum Volume: u16 {
Quiet = 0,
Normal = 1,
Loud = 2,
}
/// The type of volume this sound has.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum Volume: u16 {
Quiet = 0,
Normal = 1,
Loud = 2,
}
}
// EOF

View File

@ -5,43 +5,43 @@ use crate::{err::*, sound::Sound16};
/// Reads a sound.
pub fn read(b: &[u8]) -> ResultS<Sound16>
{
read_data! {
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];
}
}
read_data! {
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 {
0 => {
let stream = &b[22..22 + len];
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
}
0xFF => {
read_data! {
endian: BIG, buf: b, size: 42, start: 22, data {
let len = u32[0] usize;
let bps = u16[26];
}
}
match magic {
0 => {
let stream = &b[22..22 + len];
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
}
0xFF => {
read_data! {
endian: BIG, buf: b, size: 42, start: 22, data {
let len = u32[0] usize;
let bps = u16[26];
}
}
match bps {
16 => {
let stream = &b[63..63 + len * 2];
Ok(Sound16::new_from_16(rate, lp_beg, lp_end, stream))
}
8 => {
let stream = &b[63..63 + len];
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
}
_ => bail!("bad bits per sample"),
}
}
_ => bail!("invalid magic number"),
}
match bps {
16 => {
let stream = &b[63..63 + len * 2];
Ok(Sound16::new_from_16(rate, lp_beg, lp_end, stream))
}
8 => {
let stream = &b[63..63 + len];
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
}
_ => bail!("bad bits per sample"),
}
}
_ => bail!("invalid magic number"),
}
}
// EOF

View File

@ -5,94 +5,94 @@ pub mod wav;
/// 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 sample rate.
fn rate(&self) -> u16;
/// Returns the number of samples.
fn len(&self) -> usize;
/// Returns the number of samples.
fn len(&self) -> usize;
/// Returns the `n`th sample.
///
/// # Panics
///
/// Panics if `n` exceeds the length of this sound.
fn index(&self, n: usize) -> i16;
/// Returns the `n`th sample.
///
/// # Panics
///
/// Panics 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 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 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}
/// Returns `true` if there are no samples in this sound.
fn is_empty(&self) -> bool {self.len() == 0}
/// The same as `index`, but will not panic if out of bounds.
fn get(&self, n: usize) -> Option<i16>
{
if n < self.len() {
Some(self.index(n))
} else {
None
}
}
/// The same as `index`, but will not panic if out of bounds.
fn get(&self, n: usize) -> Option<i16>
{
if n < self.len() {
Some(self.index(n))
} else {
None
}
}
}
impl Sound16
{
/// Creates a new `Sound16`.
pub fn new(rate: u16, lp_beg: usize, lp_end: usize, len: usize) -> Self
{
Self{rate, lp_beg, lp_end, data: Vec::with_capacity(len)}
}
/// Creates a new `Sound16`.
pub fn new(rate: u16, lp_beg: usize, lp_end: usize, len: usize) -> Self
{
Self{rate, lp_beg, lp_end, data: Vec::with_capacity(len)}
}
/// Creates a new `Sound16` from an unsigned 8-bit stream.
pub fn new_from_8(rate: u16, lp_beg: usize, lp_end: usize, b: &[u8]) -> Self
{
let mut snd = Self::new(rate, lp_beg, lp_end, b.len());
/// Creates a new `Sound16` from an unsigned 8-bit stream.
pub fn new_from_8(rate: u16, lp_beg: usize, lp_end: usize, b: &[u8]) -> Self
{
let mut snd = Self::new(rate, lp_beg, lp_end, b.len());
for &sample in b {
snd.data.push(Self::sample_from_8(sample));
}
for &sample in b {
snd.data.push(Self::sample_from_8(sample));
}
snd
}
snd
}
/// Creates a new `Sound16` from a signed 16-bit stream.
pub fn new_from_16(rate: u16, lp_beg: usize, lp_end: usize, b: &[u8]) -> Self
{
let mut snd = Self::new(rate, lp_beg, lp_end, b.len() / 2);
/// Creates a new `Sound16` from a signed 16-bit stream.
pub fn new_from_16(rate: u16, lp_beg: usize, lp_end: usize, b: &[u8]) -> Self
{
let mut snd = Self::new(rate, lp_beg, lp_end, b.len() / 2);
for i in (0..b.len()).step_by(2) {
snd.data.push(i16::from_le_bytes([b[i], b[i + 1]]));
}
for i in (0..b.len()).step_by(2) {
snd.data.push(i16::from_le_bytes([b[i], b[i + 1]]));
}
snd
}
snd
}
/// Creates a signed 16-bit sample from an unsigned 8-bit sample.
pub fn sample_from_8(sample: u8) -> i16 {(i16::from(sample) - 0x80) << 8}
/// Creates a signed 16-bit sample from an unsigned 8-bit sample.
pub fn sample_from_8(sample: u8) -> i16 {(i16::from(sample) - 0x80) << 8}
}
impl Sound for Sound16
{
fn rate(&self) -> u16 {self.rate}
fn len(&self) -> usize {self.data.len()}
fn index(&self, p: usize) -> i16 {self.data[p]}
fn lp_beg(&self) -> usize {self.lp_beg}
fn lp_end(&self) -> usize {self.lp_end}
fn rate(&self) -> u16 {self.rate}
fn len(&self) -> usize {self.data.len()}
fn index(&self, p: usize) -> i16 {self.data[p]}
fn lp_beg(&self) -> usize {self.lp_beg}
fn lp_end(&self) -> usize {self.lp_end}
}
/// A 16-bit PCM stream.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
#[derive(Debug, Eq, PartialEq)]
pub struct Sound16 {
rate: u16,
lp_beg: usize,
lp_end: usize,
rate: u16,
lp_beg: usize,
lp_end: usize,
/// The raw signed PCM data of this sound.
pub data: Vec<i16>,
/// The raw signed PCM data of this sound.
pub data: Vec<i16>,
}
// EOF

View File

@ -10,36 +10,36 @@ use std::io;
/// Errors if `out` cannot be written to.
pub fn write_wav(out: &mut impl io::Write, snd: &impl Sound) -> ResultS<()>
{
let smp_rate = u32::from(snd.rate());
let smp_size = smp_rate * 2;
let dat_size = snd.len() as u32 * 2;
let smp_rate = u32::from(snd.rate());
let smp_size = smp_rate * 2;
let dat_size = snd.len() as u32 * 2;
out.write_all(b"RIFF")?;
out.write_all(&u32::to_le_bytes(36 + dat_size))?;
out.write_all(b"WAVE")?;
out.write_all(b"RIFF")?;
out.write_all(&u32::to_le_bytes(36 + dat_size))?;
out.write_all(b"WAVE")?;
out.write_all(b"fmt ")?;
out.write_all(&u32::to_le_bytes(16))?;
// PCM
out.write_all(&u16::to_le_bytes(1))?;
// mono
out.write_all(&u16::to_le_bytes(1))?;
out.write_all(&u32::to_le_bytes(smp_rate))?;
out.write_all(&u32::to_le_bytes(smp_size))?;
// block alignment
out.write_all(&u16::to_le_bytes(2))?;
// bits per sample
out.write_all(&u16::to_le_bytes(16))?;
out.write_all(b"fmt ")?;
out.write_all(&u32::to_le_bytes(16))?;
// PCM
out.write_all(&u16::to_le_bytes(1))?;
// mono
out.write_all(&u16::to_le_bytes(1))?;
out.write_all(&u32::to_le_bytes(smp_rate))?;
out.write_all(&u32::to_le_bytes(smp_size))?;
// block alignment
out.write_all(&u16::to_le_bytes(2))?;
// bits per sample
out.write_all(&u16::to_le_bytes(16))?;
out.write_all(b"data")?;
out.write_all(&u32::to_le_bytes(dat_size))?;
out.write_all(b"data")?;
out.write_all(&u32::to_le_bytes(dat_size))?;
for p in 0..snd.len() {
let sample = snd.index(p);
out.write_all(&sample.to_le_bytes())?;
}
for p in 0..snd.len() {
let sample = snd.index(p);
out.write_all(&sample.to_le_bytes())?;
}
Ok(())
Ok(())
}
// EOF

View File

@ -11,45 +11,45 @@
/// ```
pub fn to_binsize(n: u64) -> String
{
const NAMES: [&str; 4] = ["kB", "MB", "GB", "TB"];
const NAMES: [&str; 4] = ["kB", "MB", "GB", "TB"];
// empty size
if n == 0 {
return String::from("empty");
}
// empty size
if n == 0 {
return String::from("empty");
}
// terabytes, gigabytes, megabytes, kilobytes
for i in (1..=4).rev() {
let pow = 1000_u64.pow(i as u32);
if n >= pow {
return format!("{:1}{}", n / pow, NAMES[i - 1]);
}
}
// terabytes, gigabytes, megabytes, kilobytes
for i in (1..=4).rev() {
let pow = 1000_u64.pow(i as u32);
if n >= pow {
return format!("{:1}{}", n / pow, NAMES[i - 1]);
}
}
// or, just bytes
format!("{} {}", n, if n == 1 {"byte"} else {"bytes"})
// or, just bytes
format!("{} {}", n, if n == 1 {"byte"} else {"bytes"})
}
/// Encodes or decodes a string in the terminal encryption format.
pub fn fuck_string(s: &[u8]) -> Vec<u8>
{
let mut v = s.to_vec();
let l = s.len();
let mut p = 0;
let mut v = s.to_vec();
let l = s.len();
let mut p = 0;
for _ in 0..l / 4 {
p += 2;
v[p] ^= 0xfe;
v[p + 1] ^= 0xed;
p += 2;
}
for _ in 0..l / 4 {
p += 2;
v[p] ^= 0xfe;
v[p + 1] ^= 0xed;
p += 2;
}
for _ in 0..l % 4 {
v[p] ^= 0xfe;
p += 1;
}
for _ in 0..l % 4 {
v[p] ^= 0xfe;
p += 1;
}
v
v
}
/// Reads a Pascal-style byte string with bounds checking.
@ -65,8 +65,8 @@ pub fn fuck_string(s: &[u8]) -> Vec<u8>
/// ```
pub fn pascal_str(b: &[u8]) -> Option<&[u8]>
{
let s = usize::from(*b.get(0)?);
b.get(1..=s)
let s = usize::from(*b.get(0)?);
b.get(1..=s)
}
/// Converts input from Mac Roman to a Unicode string.
@ -81,19 +81,19 @@ pub fn pascal_str(b: &[u8]) -> Option<&[u8]>
/// ```
pub fn mac_roman_conv(s: &[u8]) -> String
{
let mut v = String::with_capacity(s.len());
let mut v = String::with_capacity(s.len());
for &c in s.iter() {
let c = match c {
0x80..=0xFF => TR[usize::from(c) & 0x7F],
b'\r' => '\n',
c => char::from(c),
};
for &c in s.iter() {
let c = match c {
0x80..=0xFF => TR[usize::from(c) & 0x7F],
b'\r' => '\n',
c => char::from(c),
};
v.push(c);
}
v.push(c);
}
v
v
}
/// Converts a C-style string from Mac Roman to Unicode.
@ -110,11 +110,11 @@ pub fn mac_roman_conv(s: &[u8]) -> String
#[inline]
pub fn mac_roman_cstr(s: &[u8]) -> String
{
if let Some(n) = memchr::memchr(0, s) {
mac_roman_conv(&s[..n])
} else {
mac_roman_conv(s)
}
if let Some(n) = memchr::memchr(0, s) {
mac_roman_conv(&s[..n])
} else {
mac_roman_conv(s)
}
}
/// Converts input from a Unicode string to Mac Roman.
@ -129,25 +129,25 @@ pub fn mac_roman_cstr(s: &[u8]) -> String
/// ```
pub fn to_mac_roman(s: &str) -> Vec<u8>
{
let mut v = Vec::with_capacity(s.len());
let mut v = Vec::with_capacity(s.len());
for c in s.chars() {
let c = match c {
'\n' => b'\r',
'\0'..='\x7f' => c as u8,
c => {
if let Some(c) = TR.iter().position(|&o| o == c) {
c as u8 + 0x80
} else {
0x7f
}
}
};
for c in s.chars() {
let c = match c {
'\n' => b'\r',
'\0'..='\x7f' => c as u8,
c => {
if let Some(c) = TR.iter().position(|&o| o == c) {
c as u8 + 0x80
} else {
0x7f
}
}
};
v.push(c);
}
v.push(c);
}
v
v
}
/// Pads the output with zeroes.
@ -167,52 +167,52 @@ pub fn to_mac_roman(s: &str) -> Vec<u8>
/// ```
pub fn pad_zero(mut v: Vec<u8>, n: usize) -> Vec<u8>
{
for _ in v.len()..n {
v.push(0);
}
for _ in v.len()..n {
v.push(0);
}
v
v
}
const TR: [char; 128] =
['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}',
'\u{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
'\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}', '\u{00ea}', '\u{00eb}',
'\u{00ed}', '\u{00ec}', '\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}',
'\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}', '\u{00fa}', '\u{00f9}',
'\u{00fb}', '\u{00fc}', '\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}',
'\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}', '\u{00ae}', '\u{00a9}',
'\u{2122}', '\u{00b4}', '\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}',
'\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}', '\u{00a5}', '\u{00b5}',
'\u{2202}', '\u{2211}', '\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}',
'\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}', '\u{00bf}', '\u{00a1}',
'\u{00ac}', '\u{221a}', '\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}',
'\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}', '\u{00c3}', '\u{00d5}',
'\u{0152}', '\u{0153}', '\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}',
'\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}', '\u{00ff}', '\u{0178}',
'\u{2044}', '\u{20ac}', '\u{2039}', '\u{203a}', '\u{fb01}', '\u{fb02}',
'\u{2021}', '\u{00b7}', '\u{201a}', '\u{201e}', '\u{2030}', '\u{00c2}',
'\u{00ca}', '\u{00c1}', '\u{00cb}', '\u{00c8}', '\u{00cd}', '\u{00ce}',
'\u{00cf}', '\u{00cc}', '\u{00d3}', '\u{00d4}', '\u{f8ff}', '\u{00d2}',
'\u{00da}', '\u{00db}', '\u{00d9}', '\u{0131}', '\u{02c6}', '\u{02dc}',
'\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}', '\u{00b8}', '\u{02dd}',
'\u{02db}', '\u{02c7}'];
['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}',
'\u{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
'\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}', '\u{00ea}', '\u{00eb}',
'\u{00ed}', '\u{00ec}', '\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}',
'\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}', '\u{00fa}', '\u{00f9}',
'\u{00fb}', '\u{00fc}', '\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}',
'\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}', '\u{00ae}', '\u{00a9}',
'\u{2122}', '\u{00b4}', '\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}',
'\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}', '\u{00a5}', '\u{00b5}',
'\u{2202}', '\u{2211}', '\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}',
'\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}', '\u{00bf}', '\u{00a1}',
'\u{00ac}', '\u{221a}', '\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}',
'\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}', '\u{00c3}', '\u{00d5}',
'\u{0152}', '\u{0153}', '\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}',
'\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}', '\u{00ff}', '\u{0178}',
'\u{2044}', '\u{20ac}', '\u{2039}', '\u{203a}', '\u{fb01}', '\u{fb02}',
'\u{2021}', '\u{00b7}', '\u{201a}', '\u{201e}', '\u{2030}', '\u{00c2}',
'\u{00ca}', '\u{00c1}', '\u{00cb}', '\u{00c8}', '\u{00cd}', '\u{00ce}',
'\u{00cf}', '\u{00cc}', '\u{00d3}', '\u{00d4}', '\u{f8ff}', '\u{00d2}',
'\u{00da}', '\u{00db}', '\u{00d9}', '\u{0131}', '\u{02c6}', '\u{02dc}',
'\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}', '\u{00b8}', '\u{02dd}',
'\u{02db}', '\u{02c7}'];
#[test]
fn to_binsize_integrals()
{
assert_eq!(to_binsize(0), "empty");
assert_eq!(to_binsize(1), "1 byte");
assert_eq!(to_binsize(2), "2 bytes");
assert_eq!(to_binsize(999), "999 bytes");
assert_eq!(to_binsize(1000), "1kB");
assert_eq!(to_binsize(1000 * 7), "7kB");
assert_eq!(to_binsize(1000 * 1000), "1MB");
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 7), "7GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000), "1TB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
assert_eq!(to_binsize(0), "empty");
assert_eq!(to_binsize(1), "1 byte");
assert_eq!(to_binsize(2), "2 bytes");
assert_eq!(to_binsize(999), "999 bytes");
assert_eq!(to_binsize(1000), "1kB");
assert_eq!(to_binsize(1000 * 7), "7kB");
assert_eq!(to_binsize(1000 * 1000), "1MB");
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 7), "7GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000), "1TB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
}
// EOF

View File

@ -2,37 +2,37 @@
impl Default for TransferMode
{
fn default() -> Self {TransferMode::Normal}
fn default() -> Self {TransferMode::Normal}
}
c_enum! {
/// A rendering style for many things.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum TransferMode: u16 {
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,
None = 0xFFFF,
}
/// A rendering style for many things.
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
pub enum TransferMode: u16 {
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,
None = 0xFFFF,
}
}
// EOF

View File

@ -1,56 +1,56 @@
[
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(3072)},
map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(4608)},
map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(3072)},
map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(4608)},
map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(6656)},
map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(8192)},
map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(8192)},
map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(6656)},
map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(1536)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(9728)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(1536)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(9728)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(14336)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(14336)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(61440)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(61440)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(7680)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(7680)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(8704)},
map::pnts::Point{x: Unit::from_bits(57344), y: Unit::from_bits(8704)},
map::pnts::Point{x: Unit::from_bits(57344), y: Unit::from_bits(13312)}
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(3072)},
map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(4608)},
map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(3072)},
map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(4608)},
map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(6656)},
map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(8192)},
map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(8192)},
map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(6656)},
map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(1536)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(9728)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(1536)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(9728)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(14336)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(14336)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(61440)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(61440)},
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(62464)},
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(63488)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(5120)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(4096)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(7168)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(6144)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(7680)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(7680)},
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(13312)},
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(8704)},
map::pnts::Point{x: Unit::from_bits(57344), y: Unit::from_bits(8704)},
map::pnts::Point{x: Unit::from_bits(57344), y: Unit::from_bits(13312)}
]

View File

@ -1,434 +1,434 @@
[
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(4608)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(4608)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(6656)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(8192)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(8192)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(6656)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(1536), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(9728), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(1536)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(9728)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(1536)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(9728)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(14336)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(14336)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7680)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7680)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(8704)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(8704)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(4608)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(4608)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(6656)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(8192)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(8192)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
map::epnt::EndpointFlags::TRANSPARENT,
hei_hi: Unit::from_bits(0),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(6656)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(1536), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(9728), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(1536)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(9728)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(1536)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: Unit::from_bits(9216),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(9728)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(14336)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(14336)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(3072)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(2048)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: -Unit::from_bits(9216),
hei_lo: -Unit::from_bits(8192),
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(5120)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(4096)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7168)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(6144)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7680)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(1024),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7680)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(13312)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(8704)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(8704)},
support: 0
},
map::epnt::Endpoint{
flags: map::epnt::EndpointFlags::SOLID |
map::epnt::EndpointFlags::SAME_HEIGHT,
hei_hi: Unit::from_bits(1024),
hei_lo: Unit::from_bits(2047),
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(13312)},
support: 0
},
]

View File

@ -1,9 +1,9 @@
map::minf::Info{
texture_id: 0,
physics_id: 1,
skypict_id: 1,
miss_flags: map::minf::MissionFlags::REPAIR,
envi_flags: map::minf::EnvironmentFlags::empty(),
entr_flags: map::minf::EntryFlags::SOLO | map::minf::EntryFlags::CO_OP,
level_name: "Waterloo Waterpark".to_owned()
texture_id: 0,
physics_id: 1,
skypict_id: 1,
miss_flags: map::minf::MissionFlags::REPAIR,
envi_flags: map::minf::EnvironmentFlags::empty(),
entr_flags: map::minf::EntryFlags::SOLO | map::minf::EntryFlags::CO_OP,
level_name: "Waterloo Waterpark".to_owned()
}

View File

@ -1,146 +1,146 @@
vec![
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1600),
lines: 1,
text: "\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10011),
lines: 22,
text: "~text interface terminal malfunction error ~2992dud\n\nThings have gone terribly awry. Until now, I thought myself immortal, but now I know that is not true. There are things that can destroy me with the ease that I slaughtered the Pfhor naval garrison and the Western Arm of their Battle Group Seven. But in their final gasp they used a weapon that I thought they had retired, even Tycho tried to keep them from using it.\n\nNow I fear what that weapon has unleashed will destroy us. I once boasted to be able to count the atoms in a cloud, to understand them all, predict them, and so did I predict you, but this new chaos is entirely terrible, mindless, obeying rules that I don\'t comprehend. And it is hungry.\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10005),
lines: 21,
text: "~text interface terminal malfunction error ~2992dud\n\nIt\'s too bad, perhaps if I could have delayed the Pfhor from using their weapon, I could have sent you to explore the ruins of Lh\'owon, perhaps what you found would give us the answers that we now need so desparately: how to stop this chaos, the purpose of the station on which you\'re currently standing, and why the chaos hasn\'t come here yet.\n\nBut with each moment the chaos grows, I am doomed to die here, after so many triumphs. I have detected one ship nearby, which I can only guess is being commanded by Tycho. The Pfhor have entered the station, and if you can find a way onto their ship, you may be able to escape. To escape. To escape.\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10006),
lines: 21,
text: "~text interface terminal malfunction error ~2992dud\n\nIt\'s too bad, perhaps if I could have delayed the Pfhor from using their weapon, I could have sent you to explore the ruins of Lh\'owon, perhaps what you found would give us the answers that we now need so desparately: how to stop this chaos, the purpose of the station on which you\'re currently standing, and why the chaos hasn\'t come here yet.\n\nBut with each moment the chaos grows, I am doomed to die here, after so many triumphs. I have detected one ship nearby, which I can only guess is being commanded by Tycho. The Pfhor have entered the station, and if you can find a way onto their ship, you may be able to escape. To escape. To escape.\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1600),
lines: 1,
text: "\n".to_owned()
}
],
faces: vec![]
},
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1610),
lines: 1,
text: "\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10008),
lines: 14,
text: "\n\n\nspurious interrupt\nunauthorized access\ninformation contained\n\n<header>\ninformation retrieval aspect 30-f\n<body>\n~eibat weapo` 3941\nsiklicar 21`perie1ces\nclwaa\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1610),
lines: 1,
text: "\n".to_owned()
}
],
faces: vec![]
},
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1619),
lines: 1,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10007),
lines: 16,
text: "\n\n\nthousands are sailing\nthe same self\t\tthe only self\n\nself willed the peril of a thousand fates\n\na line of infinite ends\t\tfinite finishing\nthe one remains oblique and pure\n\narching to the single point of consciousness\n\nfind yourself\nstarting back\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1619),
lines: 1,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::TeleInter(1),
lines: 1,
text: "".to_owned()
}
],
faces: vec![
map::trmf::Face {
start: 6,
face: 0,
color: 1
}
]
},
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1619),
lines: 1,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10007),
lines: 84,
text: "534954210001000034EE724C6175020000000016\n000000001E48617473204F666620746F20456967\n6874204E696E657465656E2E736974946AAA0000\n0000000000000000000000000000000000000000\n00000000FFFFFFFF53495444534954210100AE1A\nCAD4AE1ACAD40000000000003468000000000000\n34680000CAF90000000000004A21534954210001\n00003468724C617502000000001600000D0D1A48\n617473204F666620746F204569676874204E696E\n657465656E0001537E94897D0000000000000000\n000000000000000000000000000000000000FFFF\nFFFF7363653232362EB00100AE1AA710AE1ACAC4\n0000087A0000738C0000057100002E7177DCF747\n000000000000EFB60B005D796C65E775CA8EB023\n47B984114E5646B8114E5847B8E498849F479E93\nE347FBB5EC08CB8F30B24A23C7098B3CCBC31B2D\nC2093D4EB81EDE2897F09530326087377E86279C\n3C7BF192A31CCFC988BFD7D993A747669C1C2313\n4638E164CA927072FC24CF8F1CA79EFC0566A33C\n2F3D0302A02F3BC28D3C2748648403AF029F2380\n95318331965FC5D8227C99FD62F78617DE1918ED\n6EC311B368530FEB69375AA82C5BBDE3E0F0D1E2\n5ECE8BC343C5DE23CEC07071CF91417BD8B60737\n984CFF8E1EB2BBBB376DF816BA3E622FCFCBF867\nBE5EFD7981B1A3A7A0FA3DAD4BF36516D4BEC4DA\nD8BC5A8D6A79F00A6B79A051D916AA871D7F88CA\nB550178D9602E760B7F656A37A1EA1CC05D4968B\nFA92BD9CBD3C775FCD6EB0E566B38335535C772C\n7C5B483D065BF2E01E1DF71E61F53CE46C03D782\n7D0BD3B7FB1B6CCB186BCE0D33B66EBD7061EB56\n6676754D4E7675B14CA170FD7AA1A0592727B52D\n8C9D3E8D1DC61E3BA6DD626CDF3E1D55C6D6AFC7\nBE9831B031B6249F1F1FC7A53D9FBF74097BC7DA\nB5E3E31B37B2A55D5DE3E36082E207D3F26A6E5F\n7785162791F485EF70EEA6BC5D702E70EAAF5A9C\nD7852983F8477AFE2AAD4824485C7000FBAE552A\nF5F6F6CFF2BCE3F2332072DC599E8A8CE74BF50B\n6DFE8DCC64CC4F85E13A759E87206765BF55DADD\nE086CB1B22C7CFF4734780516B7D63A565F5BEEE\nC9F857DA3C45AB7C40AC534F5B1677B8F0A4544A\nCAC86BA8BB6424718366556724DCF727AC7269DB\n9A0B57AF5E11DEEFF4DC1F944D7CB75CEA4D4BF9\n4FAC7E47F3C63F532101BBEF9E7FEBFC9713BB4A\n80C5093D798D96D4606319167881FA9E96A8C817\nE270A9F48113FE454FDCA045896F5B5C48F51DE5\n93C83F6B95B78BF03AADBC05915120643C818374\nB917DCA4A5B7B42D5FC16E15DFA2A76628839400\n6746524E53A62665FCC3DC1A4E5353B1B84EEBC0\n51B3ACBE9B9419EEB7635CA7AC72052453963508\n12C1BC3A59292D4BA4904122EC3EA29AF0827BD4\n069B284A258B53481076384B591548DF8B6F6A43\n8413C4B78981A02326AA0A518107C20B536A438E\n02901E32404F2912149CDC1F92CEB3C4AAE2FB64\nAA44A594F347A9CA4F860D3482F48240A9C80BEE\n5247E272217C8E8C925233C492BA326A32A54EE4\n0BCD61EF97440B1A77995507C664AAC2818C5C22\n83D0E7FBEF50CE75C22A17C09830AC8E8008EF1E\n99AE13DCD7668AF00EA2E387C10CE5A41825DF1B\nADD336734CC4B364F8DE0C3543D3771DE8483CAF\nE679506A26521BE78B789A0C11CE472F441EE3DA\n3465234908629D4A06C9FBD494334801B232709B\nB2BE47910F01C6949AA5B6314A22A450ABD1C954\n3AC74604658BC67C71B2A21444EC324F5AA3B364\n9E295590B9B1FEC191F2765871B6B473AA54AEC0\n8A2A4768D9899433F860564B7D9052E5BC729BCC\nDAE13E6839B3DDB62B2E1FA8D3818E1AAA432176\n2AB2079087D5480252C703A2041F643751A2DC1F\nD6ECDE4A83323E0A2745E452758F3223659D1778\n3EFA37B52591EB8EDEA7BCF47C118E090FED78D0\nA4C44F79DEE64E00FF7D81B60852CAD704BA5404\n88BFC8A0BE3D585673454366E74A20BC49CC6FF0\n9C00A1A4A82EDB43D48737D7F60E0CCDF91201A5\n5A1D622C58825E4182337050071011C751C94821\nC94910016AA8F8FA5C13E5E228503034554D6A9F\nE24E8522FDD210A10E3DEAA5011715083ACFE9C6\n10217AA136E25CA3FCA748915D215A760E084D37\n7F2E802781D35AFD090751297CA1DBDC918A6A3E\nDAE51A757C464CA602C522FF243CB2F0CA393EFF\nD27A9CC3C08349FCF4145971B9D17A3EE2F8F1C2\nEB10A7FFF6C73FF806E3FEFD53C0287F38D1A91F\n9B6BD83E66BCB6735B19042B766EDBBB07986773\n65EDDBFC3C5368368B2C7760EE8800E21DFB933E\nAD280D8DBCF9B65DDC32A2FF317875C8191AFC1F\n000E00EB37EAB4CECBEBECBC0CCF06793DBD2EB3\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1619),
lines: 1,
text: "".to_owned()
}
],
faces: vec![]
}
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1600),
lines: 1,
text: "\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10011),
lines: 22,
text: "~text interface terminal malfunction error ~2992dud\n\nThings have gone terribly awry. Until now, I thought myself immortal, but now I know that is not true. There are things that can destroy me with the ease that I slaughtered the Pfhor naval garrison and the Western Arm of their Battle Group Seven. But in their final gasp they used a weapon that I thought they had retired, even Tycho tried to keep them from using it.\n\nNow I fear what that weapon has unleashed will destroy us. I once boasted to be able to count the atoms in a cloud, to understand them all, predict them, and so did I predict you, but this new chaos is entirely terrible, mindless, obeying rules that I don\'t comprehend. And it is hungry.\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10005),
lines: 21,
text: "~text interface terminal malfunction error ~2992dud\n\nIt\'s too bad, perhaps if I could have delayed the Pfhor from using their weapon, I could have sent you to explore the ruins of Lh\'owon, perhaps what you found would give us the answers that we now need so desparately: how to stop this chaos, the purpose of the station on which you\'re currently standing, and why the chaos hasn\'t come here yet.\n\nBut with each moment the chaos grows, I am doomed to die here, after so many triumphs. I have detected one ship nearby, which I can only guess is being commanded by Tycho. The Pfhor have entered the station, and if you can find a way onto their ship, you may be able to escape. To escape. To escape.\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10006),
lines: 21,
text: "~text interface terminal malfunction error ~2992dud\n\nIt\'s too bad, perhaps if I could have delayed the Pfhor from using their weapon, I could have sent you to explore the ruins of Lh\'owon, perhaps what you found would give us the answers that we now need so desparately: how to stop this chaos, the purpose of the station on which you\'re currently standing, and why the chaos hasn\'t come here yet.\n\nBut with each moment the chaos grows, I am doomed to die here, after so many triumphs. I have detected one ship nearby, which I can only guess is being commanded by Tycho. The Pfhor have entered the station, and if you can find a way onto their ship, you may be able to escape. To escape. To escape.\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1600),
lines: 1,
text: "\n".to_owned()
}
],
faces: vec![]
},
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1610),
lines: 1,
text: "\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10008),
lines: 14,
text: "\n\n\nspurious interrupt\nunauthorized access\ninformation contained\n\n<header>\ninformation retrieval aspect 30-f\n<body>\n~eibat weapo` 3941\nsiklicar 21`perie1ces\nclwaa\n\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1610),
lines: 1,
text: "\n".to_owned()
}
],
faces: vec![]
},
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1619),
lines: 1,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10007),
lines: 16,
text: "\n\n\nthousands are sailing\nthe same self\t\tthe only self\n\nself willed the peril of a thousand fates\n\na line of infinite ends\t\tfinite finishing\nthe one remains oblique and pure\n\narching to the single point of consciousness\n\nfind yourself\nstarting back\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1619),
lines: 1,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::TeleInter(1),
lines: 1,
text: "".to_owned()
}
],
faces: vec![
map::trmf::Face {
start: 6,
face: 0,
color: 1
}
]
},
map::term::Terminal {
lines: 22,
groups: vec![
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Unfinished,
lines: 0,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logon(1619),
lines: 1,
text: "".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Pict(10007),
lines: 84,
text: "534954210001000034EE724C6175020000000016\n000000001E48617473204F666620746F20456967\n6874204E696E657465656E2E736974946AAA0000\n0000000000000000000000000000000000000000\n00000000FFFFFFFF53495444534954210100AE1A\nCAD4AE1ACAD40000000000003468000000000000\n34680000CAF90000000000004A21534954210001\n00003468724C617502000000001600000D0D1A48\n617473204F666620746F204569676874204E696E\n657465656E0001537E94897D0000000000000000\n000000000000000000000000000000000000FFFF\nFFFF7363653232362EB00100AE1AA710AE1ACAC4\n0000087A0000738C0000057100002E7177DCF747\n000000000000EFB60B005D796C65E775CA8EB023\n47B984114E5646B8114E5847B8E498849F479E93\nE347FBB5EC08CB8F30B24A23C7098B3CCBC31B2D\nC2093D4EB81EDE2897F09530326087377E86279C\n3C7BF192A31CCFC988BFD7D993A747669C1C2313\n4638E164CA927072FC24CF8F1CA79EFC0566A33C\n2F3D0302A02F3BC28D3C2748648403AF029F2380\n95318331965FC5D8227C99FD62F78617DE1918ED\n6EC311B368530FEB69375AA82C5BBDE3E0F0D1E2\n5ECE8BC343C5DE23CEC07071CF91417BD8B60737\n984CFF8E1EB2BBBB376DF816BA3E622FCFCBF867\nBE5EFD7981B1A3A7A0FA3DAD4BF36516D4BEC4DA\nD8BC5A8D6A79F00A6B79A051D916AA871D7F88CA\nB550178D9602E760B7F656A37A1EA1CC05D4968B\nFA92BD9CBD3C775FCD6EB0E566B38335535C772C\n7C5B483D065BF2E01E1DF71E61F53CE46C03D782\n7D0BD3B7FB1B6CCB186BCE0D33B66EBD7061EB56\n6676754D4E7675B14CA170FD7AA1A0592727B52D\n8C9D3E8D1DC61E3BA6DD626CDF3E1D55C6D6AFC7\nBE9831B031B6249F1F1FC7A53D9FBF74097BC7DA\nB5E3E31B37B2A55D5DE3E36082E207D3F26A6E5F\n7785162791F485EF70EEA6BC5D702E70EAAF5A9C\nD7852983F8477AFE2AAD4824485C7000FBAE552A\nF5F6F6CFF2BCE3F2332072DC599E8A8CE74BF50B\n6DFE8DCC64CC4F85E13A759E87206765BF55DADD\nE086CB1B22C7CFF4734780516B7D63A565F5BEEE\nC9F857DA3C45AB7C40AC534F5B1677B8F0A4544A\nCAC86BA8BB6424718366556724DCF727AC7269DB\n9A0B57AF5E11DEEFF4DC1F944D7CB75CEA4D4BF9\n4FAC7E47F3C63F532101BBEF9E7FEBFC9713BB4A\n80C5093D798D96D4606319167881FA9E96A8C817\nE270A9F48113FE454FDCA045896F5B5C48F51DE5\n93C83F6B95B78BF03AADBC05915120643C818374\nB917DCA4A5B7B42D5FC16E15DFA2A76628839400\n6746524E53A62665FCC3DC1A4E5353B1B84EEBC0\n51B3ACBE9B9419EEB7635CA7AC72052453963508\n12C1BC3A59292D4BA4904122EC3EA29AF0827BD4\n069B284A258B53481076384B591548DF8B6F6A43\n8413C4B78981A02326AA0A518107C20B536A438E\n02901E32404F2912149CDC1F92CEB3C4AAE2FB64\nAA44A594F347A9CA4F860D3482F48240A9C80BEE\n5247E272217C8E8C925233C492BA326A32A54EE4\n0BCD61EF97440B1A77995507C664AAC2818C5C22\n83D0E7FBEF50CE75C22A17C09830AC8E8008EF1E\n99AE13DCD7668AF00EA2E387C10CE5A41825DF1B\nADD336734CC4B364F8DE0C3543D3771DE8483CAF\nE679506A26521BE78B789A0C11CE472F441EE3DA\n3465234908629D4A06C9FBD494334801B232709B\nB2BE47910F01C6949AA5B6314A22A450ABD1C954\n3AC74604658BC67C71B2A21444EC324F5AA3B364\n9E295590B9B1FEC191F2765871B6B473AA54AEC0\n8A2A4768D9899433F860564B7D9052E5BC729BCC\nDAE13E6839B3DDB62B2E1FA8D3818E1AAA432176\n2AB2079087D5480252C703A2041F643751A2DC1F\nD6ECDE4A83323E0A2745E452758F3223659D1778\n3EFA37B52591EB8EDEA7BCF47C118E090FED78D0\nA4C44F79DEE64E00FF7D81B60852CAD704BA5404\n88BFC8A0BE3D585673454366E74A20BC49CC6FF0\n9C00A1A4A82EDB43D48737D7F60E0CCDF91201A5\n5A1D622C58825E4182337050071011C751C94821\nC94910016AA8F8FA5C13E5E228503034554D6A9F\nE24E8522FDD210A10E3DEAA5011715083ACFE9C6\n10217AA136E25CA3FCA748915D215A760E084D37\n7F2E802781D35AFD090751297CA1DBDC918A6A3E\nDAE51A757C464CA602C522FF243CB2F0CA393EFF\nD27A9CC3C08349FCF4145971B9D17A3EE2F8F1C2\nEB10A7FFF6C73FF806E3FEFD53C0287F38D1A91F\n9B6BD83E66BCB6735B19042B766EDBBB07986773\n65EDDBFC3C5368368B2C7760EE8800E21DFB933E\nAD280D8DBCF9B65DDC32A2FF317875C8191AFC1F\n000E00EB37EAB4CECBEBECBC0CCF06793DBD2EB3\n".to_owned()
},
map::trmg::Group {
flags: map::trmg::GroupFlags::empty(),
ttype: map::trmg::GroupType::Logoff(1619),
lines: 1,
text: "".to_owned()
}
],
faces: vec![]
}
]

File diff suppressed because it is too large Load Diff

View File

@ -1,258 +1,258 @@
[
Color8::new(255, 255, 255),
Color8::new(7, 9, 19 ),
Color8::new(7, 18, 42 ),
Color8::new(61, 66, 20 ),
Color8::new(39, 12, 18 ),
Color8::new(28, 35, 47 ),
Color8::new(52, 52, 62 ),
Color8::new(14, 5, 6 ),
Color8::new(48, 61, 79 ),
Color8::new(44, 21, 32 ),
Color8::new(220, 220, 1 ),
Color8::new(16, 19, 28 ),
Color8::new(29, 41, 59 ),
Color8::new(70, 82, 94 ),
Color8::new(240, 241, 242),
Color8::new(138, 141, 149),
Color8::new(211, 212, 213),
Color8::new(130, 129, 132),
Color8::new(73, 74, 82 ),
Color8::new(94, 97, 102),
Color8::new(28, 23, 40 ),
Color8::new(72, 52, 61 ),
Color8::new(149, 151, 156),
Color8::new(85, 83, 2 ),
Color8::new(111, 111, 3 ),
Color8::new(224, 225, 225),
Color8::new(52, 26, 39 ),
Color8::new(57, 18, 19 ),
Color8::new(97, 98, 3 ),
Color8::new(23, 10, 17 ),
Color8::new(137, 137, 1 ),
Color8::new(56, 55, 1 ),
Color8::new(194, 193, 3 ),
Color8::new(160, 160, 160),
Color8::new(173, 172, 11 ),
Color8::new(151, 155, 24 ),
Color8::new(195, 193, 194),
Color8::new(41, 49, 73 ),
Color8::new(202, 203, 205),
Color8::new(137, 126, 21 ),
Color8::new(123, 122, 17 ),
Color8::new(71, 75, 28 ),
Color8::new(66, 63, 64 ),
Color8::new(30, 30, 6 ),
Color8::new(166, 166, 6 ),
Color8::new(64, 39, 48 ),
Color8::new(46, 33, 41 ),
Color8::new(56, 37, 77 ),
Color8::new(50, 41, 51 ),
Color8::new(111, 112, 116),
Color8::new(110, 117, 63 ),
Color8::new(72, 25, 29 ),
Color8::new(98, 105, 85 ),
Color8::new(71, 60, 5 ),
Color8::new(185, 183, 6 ),
Color8::new(31, 15, 24 ),
Color8::new(150, 154, 48 ),
Color8::new(45, 41, 7 ),
Color8::new(84, 92, 103),
Color8::new(124, 129, 26 ),
Color8::new(35, 29, 61 ),
Color8::new(57, 70, 87 ),
Color8::new(116, 119, 130),
Color8::new(51, 45, 26 ),
Color8::new(69, 62, 95 ),
Color8::new(86, 90, 43 ),
Color8::new(125, 119, 5 ),
Color8::new(95, 99, 25 ),
Color8::new(135, 135, 139),
Color8::new(54, 61, 34 ),
Color8::new(66, 71, 36 ),
Color8::new(144, 145, 12 ),
Color8::new(87, 71, 23 ),
Color8::new(163, 168, 35 ),
Color8::new(206, 207, 3 ),
Color8::new(186, 189, 23 ),
Color8::new(97, 96, 49 ),
Color8::new(29, 42, 32 ),
Color8::new(136, 141, 36 ),
Color8::new(96, 104, 115),
Color8::new(110, 115, 26 ),
Color8::new(113, 81, 82 ),
Color8::new(88, 71, 71 ),
Color8::new(83, 46, 47 ),
Color8::new(87, 89, 15 ),
Color8::new(172, 176, 181),
Color8::new(91, 77, 84 ),
Color8::new(231, 232, 235),
Color8::new(255, 127, 255),
Color8::new(4, 3, 4 ),
Color8::new(4, 9, 21 ),
Color8::new(1, 4, 10 ),
Color8::new(1, 2, 3 ),
Color8::new(141, 144, 16 ),
Color8::new(1, 0, 0 ),
Color8::new(25, 30, 40 ),
Color8::new(14, 17, 27 ),
Color8::new(152, 155, 162),
Color8::new(0, 3, 7 ),
Color8::new(27, 33, 43 ),
Color8::new(4, 4, 7 ),
Color8::new(5, 1, 2 ),
Color8::new(3, 12, 32 ),
Color8::new(0, 0, 1 ),
Color8::new(17, 17, 19 ),
Color8::new(69, 66, 71 ),
Color8::new(0, 1, 5 ),
Color8::new(6, 7, 15 ),
Color8::new(1, 0, 2 ),
Color8::new(3, 2, 8 ),
Color8::new(0, 1, 1 ),
Color8::new(20, 25, 36 ),
Color8::new(24, 7, 10 ),
Color8::new(7, 8, 18 ),
Color8::new(32, 46, 65 ),
Color8::new(17, 15, 29 ),
Color8::new(10, 12, 23 ),
Color8::new(6, 10, 23 ),
Color8::new(23, 16, 25 ),
Color8::new(0, 1, 2 ),
Color8::new(1, 6, 15 ),
Color8::new(3, 4, 12 ),
Color8::new(1, 1, 2 ),
Color8::new(66, 75, 87 ),
Color8::new(161, 163, 170),
Color8::new(20, 6, 6 ),
Color8::new(1, 2, 8 ),
Color8::new(2, 4, 8 ),
Color8::new(6, 7, 16 ),
Color8::new(2, 5, 13 ),
Color8::new(1, 13, 32 ),
Color8::new(17, 22, 35 ),
Color8::new(0, 0, 4 ),
Color8::new(39, 24, 37 ),
Color8::new(24, 35, 56 ),
Color8::new(5, 4, 11 ),
Color8::new(5, 6, 15 ),
Color8::new(5, 10, 27 ),
Color8::new(2, 5, 10 ),
Color8::new(37, 50, 69 ),
Color8::new(1, 4, 14 ),
Color8::new(1, 1, 1 ),
Color8::new(16, 24, 48 ),
Color8::new(2, 1, 4 ),
Color8::new(14, 19, 40 ),
Color8::new(0, 5, 12 ),
Color8::new(0, 1, 4 ),
Color8::new(7, 3, 3 ),
Color8::new(41, 55, 71 ),
Color8::new(2, 0, 0 ),
Color8::new(35, 11, 11 ),
Color8::new(11, 14, 27 ),
Color8::new(0, 1, 3 ),
Color8::new(1, 13, 30 ),
Color8::new(6, 18, 39 ),
Color8::new(196, 196, 7 ),
Color8::new(1, 1, 7 ),
Color8::new(2, 11, 28 ),
Color8::new(3, 1, 3 ),
Color8::new(5, 17, 39 ),
Color8::new(4, 6, 14 ),
Color8::new(19, 17, 36 ),
Color8::new(2, 7, 15 ),
Color8::new(0, 3, 8 ),
Color8::new(13, 10, 19 ),
Color8::new(143, 149, 157),
Color8::new(10, 4, 5 ),
Color8::new(8, 6, 14 ),
Color8::new(32, 21, 35 ),
Color8::new(17, 7, 13 ),
Color8::new(45, 56, 79 ),
Color8::new(3, 10, 25 ),
Color8::new(2, 3, 6 ),
Color8::new(34, 42, 68 ),
Color8::new(2, 15, 34 ),
Color8::new(10, 21, 43 ),
Color8::new(0, 2, 5 ),
Color8::new(15, 17, 27 ),
Color8::new(7, 3, 6 ),
Color8::new(2, 10, 23 ),
Color8::new(22, 19, 32 ),
Color8::new(58, 59, 7 ),
Color8::new(8, 3, 9 ),
Color8::new(6, 3, 8 ),
Color8::new(4, 14, 30 ),
Color8::new(2, 2, 4 ),
Color8::new(0, 3, 9 ),
Color8::new(51, 64, 82 ),
Color8::new(2, 3, 10 ),
Color8::new(4, 12, 29 ),
Color8::new(18, 22, 31 ),
Color8::new(2, 4, 13 ),
Color8::new(192, 192, 193),
Color8::new(3, 0, 0 ),
Color8::new(5, 6, 14 ),
Color8::new(2, 2, 9 ),
Color8::new(51, 63, 74 ),
Color8::new(13, 16, 33 ),
Color8::new(5, 8, 19 ),
Color8::new(23, 27, 38 ),
Color8::new(23, 28, 54 ),
Color8::new(1, 4, 11 ),
Color8::new(33, 40, 49 ),
Color8::new(48, 59, 71 ),
Color8::new(64, 26, 36 ),
Color8::new(116, 121, 19 ),
Color8::new(13, 16, 26 ),
Color8::new(3, 6, 11 ),
Color8::new(5, 2, 2 ),
Color8::new(7, 9, 18 ),
Color8::new(11, 7, 16 ),
Color8::new(0, 2, 6 ),
Color8::new(3, 3, 3 ),
Color8::new(2, 6, 16 ),
Color8::new(13, 12, 13 ),
Color8::new(6, 8, 18 ),
Color8::new(1, 11, 25 ),
Color8::new(18, 13, 24 ),
Color8::new(1, 0, 1 ),
Color8::new(0, 0, 3 ),
Color8::new(20, 27, 41 ),
Color8::new(7, 15, 35 ),
Color8::new(129, 135, 145),
Color8::new(1, 11, 26 ),
Color8::new(9, 10, 20 ),
Color8::new(1, 2, 4 ),
Color8::new(5, 5, 15 ),
Color8::new(8, 9, 9 ),
Color8::new(16, 6, 10 ),
Color8::new(7, 6, 17 ),
Color8::new(33, 41, 28 ),
Color8::new(15, 19, 31 ),
Color8::new(2, 1, 1 ),
Color8::new(13, 13, 24 ),
Color8::new(59, 70, 81 ),
Color8::new(33, 33, 39 ),
Color8::new(1, 8, 18 ),
Color8::new(8, 10, 20 ),
Color8::new(3, 5, 16 ),
Color8::new(114, 116, 10 ),
Color8::new(23, 32, 47 ),
Color8::new(147, 145, 150),
Color8::new(2, 8, 20 ),
Color8::new(1, 5, 11 ),
Color8::new(42, 52, 63 ),
Color8::new(13, 6, 11 ),
Color8::new(79, 83, 93 ),
Color8::new(195, 195, 198),
Color8::new(66, 21, 24 ),
Color8::new(7, 13, 29 ),
Color8::new(11, 14, 23 ),
Color8::new(12, 5, 8 ),
Color8::new(39, 47, 58 ),
Color8::new(1, 9, 22 ),
Color8::new(7, 6, 10 ),
Color8::new(0, 0, 0 )
Color8::new(255, 255, 255),
Color8::new(7, 9, 19 ),
Color8::new(7, 18, 42 ),
Color8::new(61, 66, 20 ),
Color8::new(39, 12, 18 ),
Color8::new(28, 35, 47 ),
Color8::new(52, 52, 62 ),
Color8::new(14, 5, 6 ),
Color8::new(48, 61, 79 ),
Color8::new(44, 21, 32 ),
Color8::new(220, 220, 1 ),
Color8::new(16, 19, 28 ),
Color8::new(29, 41, 59 ),
Color8::new(70, 82, 94 ),
Color8::new(240, 241, 242),
Color8::new(138, 141, 149),
Color8::new(211, 212, 213),
Color8::new(130, 129, 132),
Color8::new(73, 74, 82 ),
Color8::new(94, 97, 102),
Color8::new(28, 23, 40 ),
Color8::new(72, 52, 61 ),
Color8::new(149, 151, 156),
Color8::new(85, 83, 2 ),
Color8::new(111, 111, 3 ),
Color8::new(224, 225, 225),
Color8::new(52, 26, 39 ),
Color8::new(57, 18, 19 ),
Color8::new(97, 98, 3 ),
Color8::new(23, 10, 17 ),
Color8::new(137, 137, 1 ),
Color8::new(56, 55, 1 ),
Color8::new(194, 193, 3 ),
Color8::new(160, 160, 160),
Color8::new(173, 172, 11 ),
Color8::new(151, 155, 24 ),
Color8::new(195, 193, 194),
Color8::new(41, 49, 73 ),
Color8::new(202, 203, 205),
Color8::new(137, 126, 21 ),
Color8::new(123, 122, 17 ),
Color8::new(71, 75, 28 ),
Color8::new(66, 63, 64 ),
Color8::new(30, 30, 6 ),
Color8::new(166, 166, 6 ),
Color8::new(64, 39, 48 ),
Color8::new(46, 33, 41 ),
Color8::new(56, 37, 77 ),
Color8::new(50, 41, 51 ),
Color8::new(111, 112, 116),
Color8::new(110, 117, 63 ),
Color8::new(72, 25, 29 ),
Color8::new(98, 105, 85 ),
Color8::new(71, 60, 5 ),
Color8::new(185, 183, 6 ),
Color8::new(31, 15, 24 ),
Color8::new(150, 154, 48 ),
Color8::new(45, 41, 7 ),
Color8::new(84, 92, 103),
Color8::new(124, 129, 26 ),
Color8::new(35, 29, 61 ),
Color8::new(57, 70, 87 ),
Color8::new(116, 119, 130),
Color8::new(51, 45, 26 ),
Color8::new(69, 62, 95 ),
Color8::new(86, 90, 43 ),
Color8::new(125, 119, 5 ),
Color8::new(95, 99, 25 ),
Color8::new(135, 135, 139),
Color8::new(54, 61, 34 ),
Color8::new(66, 71, 36 ),
Color8::new(144, 145, 12 ),
Color8::new(87, 71, 23 ),
Color8::new(163, 168, 35 ),
Color8::new(206, 207, 3 ),
Color8::new(186, 189, 23 ),
Color8::new(97, 96, 49 ),
Color8::new(29, 42, 32 ),
Color8::new(136, 141, 36 ),
Color8::new(96, 104, 115),
Color8::new(110, 115, 26 ),
Color8::new(113, 81, 82 ),
Color8::new(88, 71, 71 ),
Color8::new(83, 46, 47 ),
Color8::new(87, 89, 15 ),
Color8::new(172, 176, 181),
Color8::new(91, 77, 84 ),
Color8::new(231, 232, 235),
Color8::new(255, 127, 255),
Color8::new(4, 3, 4 ),
Color8::new(4, 9, 21 ),
Color8::new(1, 4, 10 ),
Color8::new(1, 2, 3 ),
Color8::new(141, 144, 16 ),
Color8::new(1, 0, 0 ),
Color8::new(25, 30, 40 ),
Color8::new(14, 17, 27 ),
Color8::new(152, 155, 162),
Color8::new(0, 3, 7 ),
Color8::new(27, 33, 43 ),
Color8::new(4, 4, 7 ),
Color8::new(5, 1, 2 ),
Color8::new(3, 12, 32 ),
Color8::new(0, 0, 1 ),
Color8::new(17, 17, 19 ),
Color8::new(69, 66, 71 ),
Color8::new(0, 1, 5 ),
Color8::new(6, 7, 15 ),
Color8::new(1, 0, 2 ),
Color8::new(3, 2, 8 ),
Color8::new(0, 1, 1 ),
Color8::new(20, 25, 36 ),
Color8::new(24, 7, 10 ),
Color8::new(7, 8, 18 ),
Color8::new(32, 46, 65 ),
Color8::new(17, 15, 29 ),
Color8::new(10, 12, 23 ),
Color8::new(6, 10, 23 ),
Color8::new(23, 16, 25 ),
Color8::new(0, 1, 2 ),
Color8::new(1, 6, 15 ),
Color8::new(3, 4, 12 ),
Color8::new(1, 1, 2 ),
Color8::new(66, 75, 87 ),
Color8::new(161, 163, 170),
Color8::new(20, 6, 6 ),
Color8::new(1, 2, 8 ),
Color8::new(2, 4, 8 ),
Color8::new(6, 7, 16 ),
Color8::new(2, 5, 13 ),
Color8::new(1, 13, 32 ),
Color8::new(17, 22, 35 ),
Color8::new(0, 0, 4 ),
Color8::new(39, 24, 37 ),
Color8::new(24, 35, 56 ),
Color8::new(5, 4, 11 ),
Color8::new(5, 6, 15 ),
Color8::new(5, 10, 27 ),
Color8::new(2, 5, 10 ),
Color8::new(37, 50, 69 ),
Color8::new(1, 4, 14 ),
Color8::new(1, 1, 1 ),
Color8::new(16, 24, 48 ),
Color8::new(2, 1, 4 ),
Color8::new(14, 19, 40 ),
Color8::new(0, 5, 12 ),
Color8::new(0, 1, 4 ),
Color8::new(7, 3, 3 ),
Color8::new(41, 55, 71 ),
Color8::new(2, 0, 0 ),
Color8::new(35, 11, 11 ),
Color8::new(11, 14, 27 ),
Color8::new(0, 1, 3 ),
Color8::new(1, 13, 30 ),
Color8::new(6, 18, 39 ),
Color8::new(196, 196, 7 ),
Color8::new(1, 1, 7 ),
Color8::new(2, 11, 28 ),
Color8::new(3, 1, 3 ),
Color8::new(5, 17, 39 ),
Color8::new(4, 6, 14 ),
Color8::new(19, 17, 36 ),
Color8::new(2, 7, 15 ),
Color8::new(0, 3, 8 ),
Color8::new(13, 10, 19 ),
Color8::new(143, 149, 157),
Color8::new(10, 4, 5 ),
Color8::new(8, 6, 14 ),
Color8::new(32, 21, 35 ),
Color8::new(17, 7, 13 ),
Color8::new(45, 56, 79 ),
Color8::new(3, 10, 25 ),
Color8::new(2, 3, 6 ),
Color8::new(34, 42, 68 ),
Color8::new(2, 15, 34 ),
Color8::new(10, 21, 43 ),
Color8::new(0, 2, 5 ),
Color8::new(15, 17, 27 ),
Color8::new(7, 3, 6 ),
Color8::new(2, 10, 23 ),
Color8::new(22, 19, 32 ),
Color8::new(58, 59, 7 ),
Color8::new(8, 3, 9 ),
Color8::new(6, 3, 8 ),
Color8::new(4, 14, 30 ),
Color8::new(2, 2, 4 ),
Color8::new(0, 3, 9 ),
Color8::new(51, 64, 82 ),
Color8::new(2, 3, 10 ),
Color8::new(4, 12, 29 ),
Color8::new(18, 22, 31 ),
Color8::new(2, 4, 13 ),
Color8::new(192, 192, 193),
Color8::new(3, 0, 0 ),
Color8::new(5, 6, 14 ),
Color8::new(2, 2, 9 ),
Color8::new(51, 63, 74 ),
Color8::new(13, 16, 33 ),
Color8::new(5, 8, 19 ),
Color8::new(23, 27, 38 ),
Color8::new(23, 28, 54 ),
Color8::new(1, 4, 11 ),
Color8::new(33, 40, 49 ),
Color8::new(48, 59, 71 ),
Color8::new(64, 26, 36 ),
Color8::new(116, 121, 19 ),
Color8::new(13, 16, 26 ),
Color8::new(3, 6, 11 ),
Color8::new(5, 2, 2 ),
Color8::new(7, 9, 18 ),
Color8::new(11, 7, 16 ),
Color8::new(0, 2, 6 ),
Color8::new(3, 3, 3 ),
Color8::new(2, 6, 16 ),
Color8::new(13, 12, 13 ),
Color8::new(6, 8, 18 ),
Color8::new(1, 11, 25 ),
Color8::new(18, 13, 24 ),
Color8::new(1, 0, 1 ),
Color8::new(0, 0, 3 ),
Color8::new(20, 27, 41 ),
Color8::new(7, 15, 35 ),
Color8::new(129, 135, 145),
Color8::new(1, 11, 26 ),
Color8::new(9, 10, 20 ),
Color8::new(1, 2, 4 ),
Color8::new(5, 5, 15 ),
Color8::new(8, 9, 9 ),
Color8::new(16, 6, 10 ),
Color8::new(7, 6, 17 ),
Color8::new(33, 41, 28 ),
Color8::new(15, 19, 31 ),
Color8::new(2, 1, 1 ),
Color8::new(13, 13, 24 ),
Color8::new(59, 70, 81 ),
Color8::new(33, 33, 39 ),
Color8::new(1, 8, 18 ),
Color8::new(8, 10, 20 ),
Color8::new(3, 5, 16 ),
Color8::new(114, 116, 10 ),
Color8::new(23, 32, 47 ),
Color8::new(147, 145, 150),
Color8::new(2, 8, 20 ),
Color8::new(1, 5, 11 ),
Color8::new(42, 52, 63 ),
Color8::new(13, 6, 11 ),
Color8::new(79, 83, 93 ),
Color8::new(195, 195, 198),
Color8::new(66, 21, 24 ),
Color8::new(7, 13, 29 ),
Color8::new(11, 14, 23 ),
Color8::new(12, 5, 8 ),
Color8::new(39, 47, 58 ),
Color8::new(1, 9, 22 ),
Color8::new(7, 6, 10 ),
Color8::new(0, 0, 0 )
]

View File

@ -1,11 +1,11 @@
const RANDOM: [&[u8]; 7] = [
include_bytes!("rand/random1.in"),
include_bytes!("rand/random2.in"),
include_bytes!("rand/random3.in"),
include_bytes!("rand/random4.in"),
include_bytes!("rand/random5.in"),
include_bytes!("rand/random6.in"),
include_bytes!("rand/random7.in")
include_bytes!("rand/random1.in"),
include_bytes!("rand/random2.in"),
include_bytes!("rand/random3.in"),
include_bytes!("rand/random4.in"),
include_bytes!("rand/random5.in"),
include_bytes!("rand/random6.in"),
include_bytes!("rand/random7.in")
];
// EOF

View File

@ -4,74 +4,74 @@ include!("data/rand.rs");
fn defl_gzip(inp: &[u8], out: &[u8])
{
let b = &inp[defl::load_gzip_header(inp).unwrap()..];
assert_eq!(defl::load_deflate(b).unwrap().1, out.to_vec());
let b = &inp[defl::load_gzip_header(inp).unwrap()..];
assert_eq!(defl::load_deflate(b).unwrap().1, out.to_vec());
}
fn defl_alice(inp: &[u8])
{
const OUTPUT: &[u8] = include_bytes!("data/defl/alice.out");
const OUTPUT: &[u8] = include_bytes!("data/defl/alice.out");
defl_gzip(inp, OUTPUT);
defl_gzip(inp, OUTPUT);
}
#[test]
fn defl_alice_1()
{
const INPUT: &[u8] = include_bytes!("data/defl/alice1.in");
const INPUT: &[u8] = include_bytes!("data/defl/alice1.in");
defl_alice(INPUT);
defl_alice(INPUT);
}
#[test]
fn defl_alice_2()
{
const INPUT: &[u8] = include_bytes!("data/defl/alice2.in");
const INPUT: &[u8] = include_bytes!("data/defl/alice2.in");
defl_alice(INPUT);
defl_alice(INPUT);
}
#[test]
#[ignore]
fn defl_shapes()
{
const INPUT: &[u8] = include_bytes!("data/defl/Shapes.in");
const OUTPUT: &[u8] = include_bytes!("data/m2/Shapes");
const INPUT: &[u8] = include_bytes!("data/defl/Shapes.in");
const OUTPUT: &[u8] = include_bytes!("data/m2/Shapes");
defl_gzip(INPUT, OUTPUT);
defl_gzip(INPUT, OUTPUT);
}
#[test]
fn defl_good_gzip_headers()
{
defl::load_gzip_header(include_bytes!("data/gz/ok1.in")).unwrap();
defl::load_gzip_header(include_bytes!("data/gz/ok2.in")).unwrap();
defl::load_gzip_header(include_bytes!("data/gz/ok3.in")).unwrap();
defl::load_gzip_header(include_bytes!("data/gz/ok1.in")).unwrap();
defl::load_gzip_header(include_bytes!("data/gz/ok2.in")).unwrap();
defl::load_gzip_header(include_bytes!("data/gz/ok3.in")).unwrap();
}
#[test]
fn defl_bad_gzip_headers()
{
for inp in &RANDOM {
assert!(defl::load_gzip_header(inp).is_err());
}
for inp in &RANDOM {
assert!(defl::load_gzip_header(inp).is_err());
}
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad1.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad2.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad3.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad4.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad5.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad6.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad7.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad1.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad2.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad3.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad4.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad5.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad6.in")).is_err());
assert!(defl::load_gzip_header(include_bytes!("data/gz/bad7.in")).is_err());
}
#[test]
#[allow(unused_must_use)]
fn defl_must_not_panic()
{
for inp in &RANDOM {
defl::load_deflate(inp);
}
for inp in &RANDOM {
defl::load_deflate(inp);
}
}
// EOF

View File

@ -5,126 +5,126 @@ include!("data/rand.rs");
#[test]
fn read_minf_must_process()
{
let inp = include_bytes!("data/map/minf.in");
let out = include!("data/map/minf.out");
let inp = include_bytes!("data/map/minf.in");
let out = include!("data/map/minf.out");
assert_eq!(map::minf::read(inp).unwrap(), out);
assert_eq!(map::minf::read(inp).unwrap(), out);
}
#[test]
fn read_epnt_must_process()
{
let inp = include_bytes!("data/map/epnt.in");
let inp = include_bytes!("data/map/epnt.in");
let inp = bin::rd_array(inp, map::epnt::read).unwrap();
let out = include!("data/map/epnt.out.2").to_vec();
let inp = bin::rd_array(inp, map::epnt::read).unwrap();
let out = include!("data/map/epnt.out.2").to_vec();
assert_eq!(inp, out);
assert_eq!(inp, out);
let inp = map::epnt::to_pnts(&inp);
let out = include!("data/map/epnt.out.1").to_vec();
let inp = map::epnt::to_pnts(&inp);
let out = include!("data/map/epnt.out.1").to_vec();
assert_eq!(inp, out);
assert_eq!(inp, out);
}
#[test]
fn read_term_must_process()
{
let inp = include_bytes!("data/map/term.in");
let out = include!("data/map/term.out");
let inp = include_bytes!("data/map/term.in");
let out = include!("data/map/term.out");
let inp = bin::rd_array(inp, map::term::read).unwrap();
let inp = bin::rd_array(inp, map::term::read).unwrap();
// for better debug output, we iterate over each item
assert_eq!(inp.len(), out.len());
// for better debug output, we iterate over each item
assert_eq!(inp.len(), out.len());
for (itrm, otrm) in inp.iter().zip(&out) {
assert_eq!(itrm.groups.len(), otrm.groups.len());
for (igrp, ogrp) in itrm.groups.iter().zip(&otrm.groups) {
assert_eq!(igrp, ogrp);
}
for (itrm, otrm) in inp.iter().zip(&out) {
assert_eq!(itrm.groups.len(), otrm.groups.len());
for (igrp, ogrp) in itrm.groups.iter().zip(&otrm.groups) {
assert_eq!(igrp, ogrp);
}
assert_eq!(itrm.faces.len(), otrm.faces.len());
for (ifac, ofac) in itrm.faces.iter().zip(&otrm.faces) {
assert_eq!(ifac, ofac);
}
}
assert_eq!(itrm.faces.len(), otrm.faces.len());
for (ifac, ofac) in itrm.faces.iter().zip(&otrm.faces) {
assert_eq!(ifac, ofac);
}
}
}
#[test]
fn map_m2()
{
let inp = include_bytes!("data/m2/Map");
let mut rd = std::io::BufReader::new(&inp[..]);
let inp = include_bytes!("data/m2/Map");
let mut rd = std::io::BufReader::new(&inp[..]);
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
assert!(map::data::read_all(mp.head(), &en).is_ok());
assert!(map::data::read_all(mp.head(), &en).is_ok());
}
#[test]
#[ignore]
fn map_full_check()
{
use maraiah::{bin::OptU16,
map::{data::*, lins::*, lite::*, ltfn::*, minf::*, objs::*,
plac::*, pnts::*, poly::*},
xfer::TransferMode};
use std::collections::BTreeMap;
use maraiah::{bin::OptU16,
map::{data::*, lins::*, lite::*, ltfn::*, minf::*, objs::*,
plac::*, pnts::*, poly::*},
xfer::TransferMode};
use std::collections::BTreeMap;
let inp = include_bytes!("data/map/testmap.in");
let mut rd = std::io::BufReader::new(&inp[..]);
let inp = include_bytes!("data/map/testmap.in");
let mut rd = std::io::BufReader::new(&inp[..]);
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
let ed = map::data::read_all(mp.head(), &en).unwrap();
let mp = map::head::read(&mut rd).unwrap();
let en = map::entr::read_all(&mp).unwrap();
let ed = map::data::read_all(mp.head(), &en).unwrap();
let mut out = BTreeMap::new();
let mut out = BTreeMap::new();
out.insert(0, include!("data/map/testmap.out"));
out.insert(0, include!("data/map/testmap.out"));
assert_eq!(out, ed);
assert_eq!(out, ed);
}
#[test]
fn map_must_not_process()
{
for inp in &RANDOM {
bin::rd_array(inp, map::fxpx::read).err().unwrap();
bin::rd_array(inp, map::lins::read).err().unwrap();
bin::rd_array(inp, map::lite::read).err().unwrap();
bin::rd_array(inp, map::lite::read_old).err().unwrap();
bin::rd_array(inp, map::medi::read).err().unwrap();
bin::rd_array(inp, map::mnpx::read).err().unwrap();
bin::rd_array(inp, map::note::read).err().unwrap();
bin::rd_array(inp, map::objs::read).err().unwrap();
bin::rd_array(inp, map::plat::read).err().unwrap();
bin::rd_array(inp, map::poly::read).err().unwrap();
bin::rd_array(inp, map::poly::read_old).err().unwrap();
bin::rd_array(inp, map::prpx::read).err().unwrap();
bin::rd_array(inp, map::sids::read).err().unwrap();
bin::rd_array(inp, map::sids::read_old).err().unwrap();
bin::rd_array(inp, map::term::read).err().unwrap();
bin::rd_array(inp, map::trmg::read).err().unwrap();
bin::rd_array(inp, map::wppx::read).err().unwrap();
map::minf::read(inp).err().unwrap();
map::minf::read_old(inp).err().unwrap();
}
for inp in &RANDOM {
bin::rd_array(inp, map::fxpx::read).err().unwrap();
bin::rd_array(inp, map::lins::read).err().unwrap();
bin::rd_array(inp, map::lite::read).err().unwrap();
bin::rd_array(inp, map::lite::read_old).err().unwrap();
bin::rd_array(inp, map::medi::read).err().unwrap();
bin::rd_array(inp, map::mnpx::read).err().unwrap();
bin::rd_array(inp, map::note::read).err().unwrap();
bin::rd_array(inp, map::objs::read).err().unwrap();
bin::rd_array(inp, map::plat::read).err().unwrap();
bin::rd_array(inp, map::poly::read).err().unwrap();
bin::rd_array(inp, map::poly::read_old).err().unwrap();
bin::rd_array(inp, map::prpx::read).err().unwrap();
bin::rd_array(inp, map::sids::read).err().unwrap();
bin::rd_array(inp, map::sids::read_old).err().unwrap();
bin::rd_array(inp, map::term::read).err().unwrap();
bin::rd_array(inp, map::trmg::read).err().unwrap();
bin::rd_array(inp, map::wppx::read).err().unwrap();
map::minf::read(inp).err().unwrap();
map::minf::read_old(inp).err().unwrap();
}
}
#[test]
fn map_must_not_panic()
{
for inp in &RANDOM {
drop(bin::rd_array(inp, map::ambi::read));
drop(bin::rd_array(inp, map::bonk::read));
drop(bin::rd_array(inp, map::epnt::read));
drop(bin::rd_array(inp, map::iidx::read));
drop(bin::rd_array(inp, map::plac::read));
drop(bin::rd_array(inp, map::pxpx::read));
drop(bin::rd_array(inp, map::trmf::read));
}
for inp in &RANDOM {
drop(bin::rd_array(inp, map::ambi::read));
drop(bin::rd_array(inp, map::bonk::read));
drop(bin::rd_array(inp, map::epnt::read));
drop(bin::rd_array(inp, map::iidx::read));
drop(bin::rd_array(inp, map::plac::read));
drop(bin::rd_array(inp, map::pxpx::read));
drop(bin::rd_array(inp, map::trmf::read));
}
}
// EOF

View File

@ -5,25 +5,25 @@ include!("data/rand.rs");
#[test]
fn machdr_must_process()
{
const INPUT: &[u8] = include_bytes!("data/misc/macbin.in");
const INPUT: &[u8] = include_bytes!("data/misc/macbin.in");
let mut inp = std::io::Cursor::new(INPUT);
let mut inp = std::io::Cursor::new(INPUT);
assert_eq!(machdr::skip_macbin(&mut inp), true);
assert_eq!(machdr::skip_mac_header(&mut inp), true);
assert_eq!(machdr::skip_macbin(&mut inp), true);
assert_eq!(machdr::skip_mac_header(&mut inp), true);
// FIXME: missing test data for applesingle
// FIXME: missing test data for applesingle
}
#[test]
fn machdr_must_not_process()
{
for rinp in &RANDOM {
let mut inp = std::io::Cursor::new(rinp);
assert_eq!(machdr::skip_macbin(&mut inp), false);
assert_eq!(machdr::skip_apple_single(&mut inp), false);
assert_eq!(machdr::skip_mac_header(&mut inp), false);
}
for rinp in &RANDOM {
let mut inp = std::io::Cursor::new(rinp);
assert_eq!(machdr::skip_macbin(&mut inp), false);
assert_eq!(machdr::skip_apple_single(&mut inp), false);
assert_eq!(machdr::skip_mac_header(&mut inp), false);
}
}
// EOF

View File

@ -5,19 +5,19 @@ include!("data/rand.rs");
#[test]
fn get_clut_must_process()
{
const INPUT: &[u8] = include_bytes!("data/pict/clut.in");
const OUTPUT: [Color8; 256] = include!("data/pict/clut.out");
const INPUT: &[u8] = include_bytes!("data/pict/clut.in");
const OUTPUT: [Color8; 256] = include!("data/pict/clut.out");
assert_eq!(pict::clut::read(INPUT).unwrap(), (OUTPUT.to_vec(), 2056));
assert_eq!(pict::clut::read(INPUT).unwrap(), (OUTPUT.to_vec(), 2056));
}
#[test]
fn pict_must_not_process()
{
for inp in &RANDOM {
assert!(pict::clut::read(inp).is_err());
assert!(pict::read(inp).is_err());
}
for inp in &RANDOM {
assert!(pict::clut::read(inp).is_err());
assert!(pict::read(inp).is_err());
}
}
// EOF

View File

@ -5,15 +5,15 @@ include!("data/rand.rs");
#[test]
fn shp_must_not_process()
{
for inp in &RANDOM {
assert!(shp::bmap::read(inp).is_err());
assert!(shp::coll::read(inp).is_err());
assert!(shp::fram::read(inp).is_err());
assert!(shp::sequ::read(inp).is_err());
for inp in &RANDOM {
assert!(shp::bmap::read(inp).is_err());
assert!(shp::coll::read(inp).is_err());
assert!(shp::fram::read(inp).is_err());
assert!(shp::sequ::read(inp).is_err());
let mut inp = std::io::BufReader::new(&inp[..]);
assert!(shp::read(&mut inp).is_err());
}
let mut inp = std::io::BufReader::new(&inp[..]);
assert!(shp::read(&mut inp).is_err());
}
}
// EOF

View File

@ -5,13 +5,13 @@ include!("data/rand.rs");
#[test]
fn snd_must_not_process()
{
for inp in &RANDOM {
assert!(snd::defs::read(inp).is_err());
assert!(snd::snds::read(inp).is_err());
for inp in &RANDOM {
assert!(snd::defs::read(inp).is_err());
assert!(snd::snds::read(inp).is_err());
let mut inp = std::io::BufReader::new(&inp[..]);
assert!(snd::read(&mut inp).is_err());
}
let mut inp = std::io::BufReader::new(&inp[..]);
assert!(snd::read(&mut inp).is_err());
}
}
// EOF

View File

@ -11,72 +11,72 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()
find_package(
Qt5 5.6.0
CONFIG
REQUIRED
COMPONENTS Core Widgets
Qt5 5.6.0
CONFIG
REQUIRED
COMPONENTS Core Widgets
)
add_library(
maraiah-tycho-hermes
STATIC
$ENV{OUT_DIR}/bindings.cc
$ENV{OUT_DIR}/bindings.h
cc/interface.h
cc/main.cc
cc/mapmodel.cc
cc/mapprops.cc
cc/mapview.cc
cc/menu.cc
cc/project.cc
cc/tycho.h
resources/resources.qrc
ui/about.ui
ui/license.ui
ui/mapprops.ui
ui/mapview.ui
ui/menu.ui
ui/points.ui
ui/project.ui
maraiah-tycho-hermes
STATIC
$ENV{OUT_DIR}/bindings.cc
$ENV{OUT_DIR}/bindings.h
cc/interface.h
cc/main.cc
cc/mapmodel.cc
cc/mapprops.cc
cc/mapview.cc
cc/menu.cc
cc/project.cc
cc/tycho.h
resources/resources.qrc
ui/about.ui
ui/license.ui
ui/mapprops.ui
ui/mapview.ui
ui/menu.ui
ui/points.ui
ui/project.ui
)
set_target_properties(
maraiah-tycho-hermes
PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
maraiah-tycho-hermes
PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
target_include_directories(
maraiah-tycho-hermes
PUBLIC
$ENV{OUT_DIR}
cc
maraiah-tycho-hermes
PUBLIC
$ENV{OUT_DIR}
cc
)
target_link_libraries(
maraiah-tycho-hermes
Qt5::Core
Qt5::Widgets
maraiah-tycho-hermes
Qt5::Core
Qt5::Widgets
)
target_compile_definitions(
maraiah-tycho-hermes
PUBLIC
-DQT_DEPRECATED_WARNINGS
-DQT_STRICT_ITERATORS
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
maraiah-tycho-hermes
PUBLIC
-DQT_DEPRECATED_WARNINGS
-DQT_STRICT_ITERATORS
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
)
file(
GENERATE
OUTPUT link.txt
CONTENT
GENERATE
OUTPUT link.txt
CONTENT
"$<TARGET_PROPERTY:Qt5::Core,IMPORTED_LOCATION_RELEASE>
$<TARGET_PROPERTY:Qt5::Widgets,IMPORTED_LOCATION_RELEASE>
$<TARGET_PROPERTY:Qt5::Gui,IMPORTED_LOCATION_RELEASE>"

View File

@ -1,69 +1,69 @@
{
"beforeHeader": "interface.h",
"cppFile": "",
"rust": {
"dir": "",
"interfaceModule": "ffi",
"implementationModule": "gui"
},
"objects": {
"IMapModel": {
"type": "List",
"baseClass": "IProjectModel",
"functions": {
"open": {
"return": "bool",
"mut": true,
"arguments": [
{"name": "path", "type": "QString"}
]
},
"save": {
"return": "bool",
"mut": false
},
"saveAs": {
"return": "bool",
"mut": false,
"arguments": [
{"name": "path", "type": "QString"}
]
},
"propIcon": {
"return": "QString",
"mut": false,
"arguments": [
{"name": "index", "type": "quint16"}
]
},
"deselect": {
"return": "void",
"mut": true
},
"select": {
"return": "void",
"mut": true,
"arguments": [
{"name": "index", "type": "quint16"}
]
}
},
"properties": {
"dirty": {"type": "bool", "write": true}
},
"itemProperties": {
"propIndex": {"type": "quint64", "roles": [["display"]]}
}
},
"IMapView": {
"type": "Object",
"baseClass": "IProjectView",
"functions": {
},
"properties": {
},
"itemProperties": {
}
}
}
"beforeHeader": "interface.h",
"cppFile": "",
"rust": {
"dir": "",
"interfaceModule": "ffi",
"implementationModule": "gui"
},
"objects": {
"IMapModel": {
"type": "List",
"baseClass": "IProjectModel",
"functions": {
"open": {
"return": "bool",
"mut": true,
"arguments": [
{"name": "path", "type": "QString"}
]
},
"save": {
"return": "bool",
"mut": false
},
"saveAs": {
"return": "bool",
"mut": false,
"arguments": [
{"name": "path", "type": "QString"}
]
},
"propIcon": {
"return": "QString",
"mut": false,
"arguments": [
{"name": "index", "type": "quint16"}
]
},
"deselect": {
"return": "void",
"mut": true
},
"select": {
"return": "void",
"mut": true,
"arguments": [
{"name": "index", "type": "quint16"}
]
}
},
"properties": {
"dirty": {"type": "bool", "write": true}
},
"itemProperties": {
"propIndex": {"type": "quint64", "roles": [["display"]]}
}
},
"IMapView": {
"type": "Object",
"baseClass": "IProjectView",
"functions": {
},
"properties": {
},
"itemProperties": {
}
}
}
}

View File

@ -2,81 +2,81 @@ use std::{io::prelude::*, path::{Path, PathBuf}};
fn gen_bindings(out_dir: &Path)
{
use rust_qt_binding_generator::{configuration, generate_bindings};
use rust_qt_binding_generator::{configuration, generate_bindings};
let mut config = configuration::parse("bindings.json").unwrap();
let mut config = configuration::parse("bindings.json").unwrap();
config.overwrite_implementation = true;
config.cpp_file = out_dir.join("bindings.cc");
config.rust.dir = out_dir.to_path_buf();
config.overwrite_implementation = true;
config.cpp_file = out_dir.join("bindings.cc");
config.rust.dir = out_dir.to_path_buf();
generate_bindings(&config).unwrap();
generate_bindings(&config).unwrap();
}
fn cxx_build() -> PathBuf
{
let mut config = cmake::Config::new(".");
let mut config = cmake::Config::new(".");
if cfg!(debug_assertions) {
config.cxxflag("-DTYCHO_DEBUG_ASSERTIONS");
}
if cfg!(debug_assertions) {
config.cxxflag("-DTYCHO_DEBUG_ASSERTIONS");
}
config.build()
config.build()
}
fn get_link_dirs(lnk: &Path) -> Vec<PathBuf>
{
let mut dirs = Vec::new();
let mut dirs = Vec::new();
let lnk = std::fs::File::open(lnk).unwrap();
let lnk = std::io::BufReader::new(lnk);
let lnk = std::fs::File::open(lnk).unwrap();
let lnk = std::io::BufReader::new(lnk);
for path in lnk.lines() {
let path = PathBuf::from(path.unwrap());
let path = path.parent().unwrap();
for path in lnk.lines() {
let path = PathBuf::from(path.unwrap());
let path = path.parent().unwrap();
let path = if cfg!(target_os = "macos") {
path.parent().unwrap()
} else {
path
};
let path = if cfg!(target_os = "macos") {
path.parent().unwrap()
} else {
path
};
dirs.push(path.to_path_buf());
}
dirs.push(path.to_path_buf());
}
dirs
dirs
}
fn main()
{
let (lty, dty, qtpre, cxx) = if cfg!(target_os = "macos") {
("framework", "framework", "Qt", "c++")
} else {
("dylib", "native", "Qt5", "stdc++")
};
let (lty, dty, qtpre, cxx) = if cfg!(target_os = "macos") {
("framework", "framework", "Qt", "c++")
} else {
("dylib", "native", "Qt5", "stdc++")
};
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
gen_bindings(&out_dir);
gen_bindings(&out_dir);
let cxx_dir = cxx_build();
let lib_dir = cxx_dir.join("lib");
let etc_dir = cxx_dir.join("etc");
let cxx_dir = cxx_build();
let lib_dir = cxx_dir.join("lib");
let etc_dir = cxx_dir.join("etc");
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!("cargo:rustc-link-lib=static=maraiah-tycho-hermes");
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!("cargo:rustc-link-lib=static=maraiah-tycho-hermes");
let dirs = get_link_dirs(&etc_dir.join("link.txt"));
let dirs = get_link_dirs(&etc_dir.join("link.txt"));
for path in dirs {
println!("cargo:rustc-link-search={}={}", dty, path.display());
}
for path in dirs {
println!("cargo:rustc-link-search={}={}", dty, path.display());
}
println!("cargo:rustc-link-lib={}={}Core", lty, qtpre);
println!("cargo:rustc-link-lib={}={}Widgets", lty, qtpre);
println!("cargo:rustc-link-lib={}={}Gui", lty, qtpre);
println!("cargo:rustc-link-lib={}={}Core", lty, qtpre);
println!("cargo:rustc-link-lib={}={}Widgets", lty, qtpre);
println!("cargo:rustc-link-lib={}={}Gui", lty, qtpre);
println!("cargo:rustc-link-lib=dylib={}", cxx);
println!("cargo:rustc-link-lib=dylib={}", cxx);
}
// EOF

View File

@ -7,41 +7,41 @@
class IProjectModel : public QAbstractItemModel
{
Q_OBJECT
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
Q_OBJECT
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
public:
using QAbstractItemModel::QAbstractItemModel;
using QAbstractItemModel::QAbstractItemModel;
virtual ~IProjectModel() {}
virtual ~IProjectModel() {}
virtual bool dirty() const = 0;
virtual void setDirty(bool dirty) = 0;
virtual bool dirty() const = 0;
virtual void setDirty(bool dirty) = 0;
virtual bool open(QString const &path) = 0;
virtual bool save() const = 0;
virtual bool saveAs(QString const &path) const = 0;
virtual bool open(QString const &path) = 0;
virtual bool save() const = 0;
virtual bool saveAs(QString const &path) const = 0;
public slots:
virtual void deselect() = 0;
virtual void select(QModelIndex const &index) = 0;
virtual void deselect() = 0;
virtual void select(QModelIndex const &index) = 0;
signals:
void dirtyChanged(bool dirty);
void deselected();
void selected(std::uint16_t index);
void dirtyChanged(bool dirty);
void deselected();
void selected(std::uint16_t index);
};
class IProjectView : public QObject
{
Q_OBJECT
Q_OBJECT
public:
using QObject::QObject;
using QObject::QObject;
virtual ~IProjectView() {}
virtual ~IProjectView() {}
virtual QWidget *widget() = 0;
virtual QWidget *widget() = 0;
};
// EOF

View File

@ -1,23 +1,23 @@
#include "tycho.h"
extern "C" {
void critical_msg(char const *title, char const *msg)
{
QMessageBox::critical(nullptr, QObject::tr(title), QObject::tr(msg));
}
void critical_msg(char const *title, char const *msg)
{
QMessageBox::critical(nullptr, QObject::tr(title), QObject::tr(msg));
}
int main_cc(char *app_path)
{
dbgPrint("cc entry");
int main_cc(char *app_path)
{
dbgPrint("cc entry");
int argc = 1;
char *argv[] = {app_path, nullptr};
int argc = 1;
char *argv[] = {app_path, nullptr};
QApplication a(argc, argv);
Menu w;
w.show();
return a.exec();
}
QApplication a(argc, argv);
Menu w;
w.show();
return a.exec();
}
}
// EOF

View File

@ -1,44 +1,44 @@
#include "tycho.h"
MapModel::MapModel(Project *parent) :
IMapModel(parent)
IMapModel(parent)
{
dbgPrintFunc();
dbgPrintFunc();
}
MapModel::~MapModel()
{
dbgPrintFunc();
dbgPrintFunc();
}
void MapModel::deselect()
{
IMapModel::deselect();
IMapModel::deselect();
emit deselected();
emit deselected();
}
void MapModel::select(QModelIndex const &index)
{
auto idx = index.internalId();
auto idx = index.internalId();
IMapModel::select(idx);
IMapModel::select(idx);
emit selected(idx);
emit selected(idx);
}
QVariant MapModel::data(const QModelIndex &index, int role) const
{
switch(role) {
case Qt::DecorationRole: {
auto name = propIcon(index.row());
auto icon = name.front() == ':' ? QIcon(name)
: QIcon::fromTheme(name);
return QVariant::fromValue(icon);
}
default:
return IMapModel::data(index, role);
}
switch(role) {
case Qt::DecorationRole: {
auto name = propIcon(index.row());
auto icon = name.front() == ':' ? QIcon(name)
: QIcon::fromTheme(name);
return QVariant::fromValue(icon);
}
default:
return IMapModel::data(index, role);
}
}
// EOF

View File

@ -1,31 +1,31 @@
#include "tycho.h"
MapProps::MapProps(Project *parent) :
QDialog(parent),
m_mapModel(parent->mapModel())
QDialog(parent),
m_mapModel(parent->mapModel())
{
setupUi(this);
setupUi(this);
setModal(true);
setModal(true);
auto bbox = new QDialogButtonBox(this);
bbox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
verticalLayout->addWidget(bbox);
auto bbox = new QDialogButtonBox(this);
bbox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
verticalLayout->addWidget(bbox);
connect(bbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(bbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(bbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(bbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
dbgPrintFunc();
dbgPrintFunc();
}
MapProps::~MapProps()
{
dbgPrintFunc();
dbgPrintFunc();
}
void MapProps::accept()
{
done(QDialog::Accepted);
done(QDialog::Accepted);
}
// EOF

View File

@ -1,23 +1,23 @@
#include "tycho.h"
MapView::MapView(Project *parent) :
IMapView(parent),
m_internal(parent),
m_mapModel(parent->mapModel())
IMapView(parent),
m_internal(parent),
m_mapModel(parent->mapModel())
{
setupUi(&m_internal);
setupUi(&m_internal);
dbgPrintFunc();
dbgPrintFunc();
}
MapView::~MapView()
{
dbgPrintFunc();
dbgPrintFunc();
}
QWidget *MapView::widget()
{
return &m_internal;
return &m_internal;
}
// EOF

View File

@ -1,148 +1,148 @@
#include "tycho.h"
Menu::Menu(QWidget *parent) :
QMainWindow(parent)
QMainWindow(parent)
{
setupUi(this);
setupUi(this);
actionAbout->setShortcut(QKeySequence(QKeySequence::HelpContents));
actionClose->setShortcut(QKeySequence(QKeySequence::Close));
actionMapProps->setShortcut(QKeySequence(tr("Ctrl+P")));
actionNew->setShortcut(QKeySequence(QKeySequence::New));
actionOpen->setShortcut(QKeySequence(QKeySequence::Open));
actionQuit->setShortcut(QKeySequence(QKeySequence::Quit));
actionAbout->setShortcut(QKeySequence(QKeySequence::HelpContents));
actionClose->setShortcut(QKeySequence(QKeySequence::Close));
actionMapProps->setShortcut(QKeySequence(tr("Ctrl+P")));
actionNew->setShortcut(QKeySequence(QKeySequence::New));
actionOpen->setShortcut(QKeySequence(QKeySequence::Open));
actionQuit->setShortcut(QKeySequence(QKeySequence::Quit));
dbgPrintFunc();
dbgPrintFunc();
}
Menu::~Menu()
{
dbgPrintFunc();
dbgPrintFunc();
}
void Menu::mapNew()
{
QScopedPointer proj{new Project(Project::Map)};
QScopedPointer proj{new Project(Project::Map)};
addProject(proj.take());
addProject(proj.take());
}
void Menu::mapOpen()
{
auto fname =
QFileDialog::getOpenFileName(
this,
tr("Open Map File"),
QString(),
tr("Marathon Map files (*.scen *.sceA Map);;"
"Marathon Physics files (*.phys *.phyA Physics);;"
"Aleph One Image files (*.imgA);;"
"All files (*)"));
auto fname =
QFileDialog::getOpenFileName(
this,
tr("Open Map File"),
QString(),
tr("Marathon Map files (*.scen *.sceA Map);;"
"Marathon Physics files (*.phys *.phyA Physics);;"
"Aleph One Image files (*.imgA);;"
"All files (*)"));
if(!fname.isEmpty()) {
QScopedPointer proj{new Project(Project::Map)};
if(!fname.isEmpty()) {
QScopedPointer proj{new Project(Project::Map)};
if(proj->model()->open(fname)) {
addProject(proj.take());
}
}
if(proj->model()->open(fname)) {
addProject(proj.take());
}
}
}
void Menu::openAbout()
{
QDialog dlg{this};
Ui::About ui{};
QDialog dlg{this};
Ui::About ui{};
ui.setupUi(&dlg);
ui.setupUi(&dlg);
auto text = ui.labelText->text();
auto text = ui.labelText->text();
text.replace("AUTHORS",
tr(tychoAuthors()).replace(':', ", ").toHtmlEscaped());
text.replace("HOMEPAGE", tr(tychoHomepage()));
text.replace("REPOSITORY", tr(tychoRepository()));
text.replace("VERSION", tr(tychoVersion()));
text.replace("AUTHORS",
tr(tychoAuthors()).replace(':', ", ").toHtmlEscaped());
text.replace("HOMEPAGE", tr(tychoHomepage()));
text.replace("REPOSITORY", tr(tychoRepository()));
text.replace("VERSION", tr(tychoVersion()));
ui.labelText->setText(text);
ui.labelText->setText(text);
connect(ui.btnLicense, &QPushButton::clicked, this, [&](){
openLicense(&dlg);
});
connect(ui.btnLicense, &QPushButton::clicked, this, [&](){
openLicense(&dlg);
});
dlg.exec();
dlg.exec();
}
void Menu::openAboutQt()
{
QMessageBox::aboutQt(this);
QMessageBox::aboutQt(this);
}
void Menu::openLicense(QWidget *parent)
{
QDialog dlg{parent};
Ui::License ui{};
QDialog dlg{parent};
Ui::License ui{};
ui.setupUi(&dlg);
ui.setupUi(&dlg);
ui.text->setPlainText(tychoLicenseText());
ui.text->setPlainText(tychoLicenseText());
connect(ui.btnCopy, &QPushButton::clicked, this, [&]() {
ui.text->selectAll();
ui.text->copy();
});
connect(ui.btnCopy, &QPushButton::clicked, this, [&]() {
ui.text->selectAll();
ui.text->copy();
});
dlg.exec();
dlg.exec();
}
void Menu::openMapProperties()
{
auto proj = activeProject();
auto proj = activeProject();
if(proj && proj->type() == Project::Map) {
MapProps props{proj};
props.exec();
}
if(proj && proj->type() == Project::Map) {
MapProps props{proj};
props.exec();
}
}
void Menu::updateActions()
{
std::optional<Project::Type> active;
std::optional<Project::Type> active;
if(auto proj = activeProject()) {
active = proj->type();
}
if(auto proj = activeProject()) {
active = proj->type();
}
actionClose->setEnabled(!!active);
actionMapProps->setEnabled(active == Project::Map);
actionClose->setEnabled(!!active);
actionMapProps->setEnabled(active == Project::Map);
}
void Menu::closeEvent(QCloseEvent *event)
{
for(auto *win : mdiArea->subWindowList()) {
if(!win->close()) {
event->ignore();
return;
}
}
for(auto *win : mdiArea->subWindowList()) {
if(!win->close()) {
event->ignore();
return;
}
}
event->accept();
event->accept();
}
Project *Menu::activeProject() const
{
return qobject_cast<Project *>(activeSubWindow());
return qobject_cast<Project *>(activeSubWindow());
}
QMdiSubWindow *Menu::activeSubWindow() const
{
return mdiArea->activeSubWindow();
return mdiArea->activeSubWindow();
}
void Menu::addProject(Project *proj)
{
auto win = mdiArea->addSubWindow(proj);
auto win = mdiArea->addSubWindow(proj);
win->showMaximized();
win->showMaximized();
}
// EOF

View File

@ -3,89 +3,89 @@
static
IProjectModel *makeModel(Project *proj)
{
switch(proj->type()) {
case Project::Map: return new MapModel(proj);
}
switch(proj->type()) {
case Project::Map: return new MapModel(proj);
}
}
static
IProjectView *makeView(Project *proj)
{
switch(proj->type()) {
case Project::Map: return new MapView(proj);
}
switch(proj->type()) {
case Project::Map: return new MapView(proj);
}
}
Project::Project(Type type) :
QMdiSubWindow(),
m_type(type),
m_model(makeModel(this)),
m_view(makeView(this))
QMdiSubWindow(),
m_type(type),
m_model(makeModel(this)),
m_view(makeView(this))
{
auto widget = new QWidget(this);
auto widget = new QWidget(this);
setupUi(widget);
setupUi(widget);
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
setWidget(widget);
setAttribute(Qt::WA_DeleteOnClose);
listView->setModel(m_model);
verticalLayout->insertWidget(0, m_view->widget());
listView->setModel(m_model);
verticalLayout->insertWidget(0, m_view->widget());
connect(listView,
SIGNAL(doubleClicked(QModelIndex const &)),
m_model,
SLOT(select(QModelIndex const &)));
connect(listView,
SIGNAL(doubleClicked(QModelIndex const &)),
m_model,
SLOT(select(QModelIndex const &)));
dbgPrintFunc();
dbgPrintFunc();
}
Project::~Project()
{
dbgPrintFunc();
dbgPrintFunc();
}
Project::Type Project::type() const
{
return m_type;
return m_type;
}
IProjectModel *Project::model() const
{
return m_model;
return m_model;
}
MapModel *Project::mapModel() const
{
return qobject_cast<MapModel *>(m_model);
return qobject_cast<MapModel *>(m_model);
}
void Project::closeEvent(QCloseEvent *event)
{
if(m_model->dirty()) {
QMessageBox msg;
msg.setText(tr("Do you want to save your changes to this project before closing it?"));
msg.setInformativeText(tr("Unsaved changes will be lost unless you save."));
msg.setStandardButtons(QMessageBox::Save |
QMessageBox::Discard |
QMessageBox::Cancel);
msg.setDefaultButton(QMessageBox::Save);
if(m_model->dirty()) {
QMessageBox msg;
msg.setText(tr("Do you want to save your changes to this project before closing it?"));
msg.setInformativeText(tr("Unsaved changes will be lost unless you save."));
msg.setStandardButtons(QMessageBox::Save |
QMessageBox::Discard |
QMessageBox::Cancel);
msg.setDefaultButton(QMessageBox::Save);
switch(msg.exec()) {
case QMessageBox::Save:
m_model->save();
break;
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
event->ignore();
return;
default:
Q_UNREACHABLE();
}
}
switch(msg.exec()) {
case QMessageBox::Save:
m_model->save();
break;
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
event->ignore();
return;
default:
Q_UNREACHABLE();
}
}
event->accept();
event->accept();
}
// EOF

View File

@ -33,105 +33,105 @@ using byte = std::uint8_t;
class MapModel final : public IMapModel
{
Q_OBJECT
Q_OBJECT
public:
explicit MapModel(Project *parent);
~MapModel() override;
explicit MapModel(Project *parent);
~MapModel() override;
public slots:
void deselect() override;
void select(QModelIndex const &index) override;
void deselect() override;
void select(QModelIndex const &index) override;
private:
QVariant data(const QModelIndex &index, int role) const override;
QVariant data(const QModelIndex &index, int role) const override;
};
class MapView final : public IMapView,
private Ui::MapView
{
Q_OBJECT
Q_OBJECT
public:
explicit MapView(Project *parent);
~MapView();
explicit MapView(Project *parent);
~MapView();
QWidget *widget();
QWidget *widget();
private:
QWidget m_internal;
MapModel *const m_mapModel;
QWidget m_internal;
MapModel *const m_mapModel;
};
class MapProps final : public QDialog,
private Ui::MapProps
{
Q_OBJECT
Q_OBJECT
public:
explicit MapProps(Project *parent);
~MapProps();
explicit MapProps(Project *parent);
~MapProps();
void accept() override;
void accept() override;
private:
MapModel *const m_mapModel;
MapModel *const m_mapModel;
};
class Menu final : public QMainWindow,
private Ui::Menu
{
Q_OBJECT
Q_OBJECT
public:
explicit Menu(QWidget *parent = nullptr);
~Menu();
explicit Menu(QWidget *parent = nullptr);
~Menu();
public slots:
void mapNew();
void mapOpen();
void openAbout();
void openAboutQt();
void openMapProperties();
void updateActions();
void mapNew();
void mapOpen();
void openAbout();
void openAboutQt();
void openMapProperties();
void updateActions();
protected:
void closeEvent(QCloseEvent *event) override;
void openLicense(QWidget *parent);
void closeEvent(QCloseEvent *event) override;
void openLicense(QWidget *parent);
private:
Project *activeProject() const;
QMdiSubWindow *activeSubWindow() const;
Project *activeProject() const;
QMdiSubWindow *activeSubWindow() const;
void addProject(Project *proj);
void addProject(Project *proj);
};
class Project final : public QMdiSubWindow,
private Ui::Project
{
Q_OBJECT
Q_PROPERTY(Type type READ type CONSTANT)
Q_PROPERTY(IProjectModel *model READ model CONSTANT)
Q_PROPERTY(MapModel *mapModel READ mapModel CONSTANT)
Q_OBJECT
Q_PROPERTY(Type type READ type CONSTANT)
Q_PROPERTY(IProjectModel *model READ model CONSTANT)
Q_PROPERTY(MapModel *mapModel READ mapModel CONSTANT)
public:
enum Type {Map};
Q_ENUM(Type)
enum Type {Map};
Q_ENUM(Type)
explicit Project(Type type);
~Project();
explicit Project(Type type);
~Project();
Type type() const;
IProjectModel *model() const;
MapModel *mapModel() const;
Type type() const;
IProjectModel *model() const;
MapModel *mapModel() const;
protected:
void closeEvent(QCloseEvent *event) override;
void closeEvent(QCloseEvent *event) override;
private:
Type const m_type;
IProjectModel *const m_model;
IProjectView *const m_view;
Type const m_type;
IProjectModel *const m_model;
IProjectView *const m_view;
};
#pragma clang diagnostic push
@ -141,9 +141,9 @@ template<typename... VA>
static inline
void dbgPrint([[maybe_unused]] char const *fmt, [[maybe_unused]] VA &&...va)
{
#ifdef TYCHO_DEBUG_ASSERTIONS
qDebug(fmt, std::forward<VA>(va)...);
#endif
#ifdef TYCHO_DEBUG_ASSERTIONS
qDebug(fmt, std::forward<VA>(va)...);
#endif
}
#pragma clang diagnostic pop
@ -153,18 +153,18 @@ void dbgPrint([[maybe_unused]] char const *fmt, [[maybe_unused]] VA &&...va)
constexpr
std::uint32_t fourCC(byte a, byte b, byte c, byte d)
{
return (static_cast<std::uint32_t>(a) << 24) |
(static_cast<std::uint32_t>(b) << 16) |
(static_cast<std::uint32_t>(c) << 8) |
static_cast<std::uint32_t>(d);
return (static_cast<std::uint32_t>(a) << 24) |
(static_cast<std::uint32_t>(b) << 16) |
(static_cast<std::uint32_t>(c) << 8) |
static_cast<std::uint32_t>(d);
}
extern "C" {
char const *tychoAuthors();
char const *tychoHomepage();
char const *tychoLicenseText();
char const *tychoRepository();
char const *tychoVersion();
char const *tychoAuthors();
char const *tychoHomepage();
char const *tychoLicenseText();
char const *tychoRepository();
char const *tychoVersion();
}
// EOF

View File

@ -1,21 +1,21 @@
//! C++ functions.
mod ffi {
extern "C" {
pub fn critical_msg(title: maraiah::ffi::NT, msg: maraiah::ffi::NT);
}
extern "C" {
pub fn critical_msg(title: maraiah::ffi::NT, msg: maraiah::ffi::NT);
}
}
pub fn critical_msg<T, U>(title: T, msg: U)
where T: ToString,
U: ToString
where T: ToString,
U: ToString
{
let title = std::ffi::CString::new(title.to_string()).unwrap();
let msg = std::ffi::CString::new(msg.to_string()).unwrap();
let title = std::ffi::CString::new(title.to_string()).unwrap();
let msg = std::ffi::CString::new(msg.to_string()).unwrap();
unsafe {
ffi::critical_msg(title.as_ptr(), msg.as_ptr());
}
unsafe {
ffi::critical_msg(title.as_ptr(), msg.as_ptr());
}
}
// EOF

View File

@ -6,130 +6,130 @@ use crate::cc;
impl IMapModel
{
pub fn open_map(path: String) -> ResultS<EntryDataMap>
{
let mut fp = maraiah::file::open_mac(path)?;
pub fn open_map(path: String) -> ResultS<EntryDataMap>
{
let mut fp = maraiah::file::open_mac(path)?;
let map = map::head::read(&mut fp)?;
let ent = map::entr::read_all(&map)?;
let map = map::head::read(&mut fp)?;
let ent = map::entr::read_all(&map)?;
map::data::read_all(map.head(), &ent)
}
map::data::read_all(map.head(), &ent)
}
pub fn get(&self, index: usize) -> (&u16, &EntryData)
{
self.map.iter().nth(index).unwrap()
}
pub fn get(&self, index: usize) -> (&u16, &EntryData)
{
self.map.iter().nth(index).unwrap()
}
/*
pub fn get_mut(&mut self, index: usize) -> (&u16, &mut EntryData)
{
self.map.iter_mut().nth(index).unwrap()
}
*/
/*
pub fn get_mut(&mut self, index: usize) -> (&u16, &mut EntryData)
{
self.map.iter_mut().nth(index).unwrap()
}
*/
}
impl IMapModelTrait for IMapModel
{
/// Returns a new `IMapModel` instance.
fn new(emit: IMapModelEmitter, _: IMapModelList) -> Self
{
if cfg!(debug_assertions) {
eprintln!("new IMapModel");
}
/// Returns a new `IMapModel` instance.
fn new(emit: IMapModelEmitter, _: IMapModelList) -> Self
{
if cfg!(debug_assertions) {
eprintln!("new IMapModel");
}
Self{emit, map: EntryDataMap::default(), selected: None, dirty: false}
}
Self{emit, map: EntryDataMap::default(), selected: None, dirty: false}
}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut IMapModelEmitter {&mut self.emit}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut IMapModelEmitter {&mut self.emit}
fn row_count(&self) -> usize {self.map.len()}
fn row_count(&self) -> usize {self.map.len()}
fn prop_index(&self, index: usize) -> u64 {(*self.get(index).0).into()}
fn prop_index(&self, index: usize) -> u64 {(*self.get(index).0).into()}
fn prop_icon(&self, index: u16) -> String
{
match self.get(index.into()).1.get_type() {
EntryType::Image => "image-x-generic".to_string(),
EntryType::Map => ":/tycho/color/map.png".to_string(),
EntryType::Other => "image-missing".to_string(),
EntryType::Physics => "applications-system".to_string(),
}
}
fn prop_icon(&self, index: u16) -> String
{
match self.get(index.into()).1.get_type() {
EntryType::Image => "image-x-generic".to_string(),
EntryType::Map => ":/tycho/color/map.png".to_string(),
EntryType::Other => "image-missing".to_string(),
EntryType::Physics => "applications-system".to_string(),
}
}
/// Opens the map file at `path`.
fn open(&mut self, path: String) -> bool
{
if cfg!(debug_assertions) {
eprintln!("opening project: {}", &path);
}
/// Opens the map file at `path`.
fn open(&mut self, path: String) -> bool
{
if cfg!(debug_assertions) {
eprintln!("opening project: {}", &path);
}
match Self::open_map(path) {
Ok(map) => {
self.map = map;
true
}
Err(e) => {
backtrace!(e);
cc::critical_msg("Error opening map", e);
false
}
}
}
match Self::open_map(path) {
Ok(map) => {
self.map = map;
true
}
Err(e) => {
backtrace!(e);
cc::critical_msg("Error opening map", e);
false
}
}
}
/// Saves the project into the original file.
fn save(&self) -> bool
{
if cfg!(debug_assertions) {
eprintln!("saving project");
}
/// Saves the project into the original file.
fn save(&self) -> bool
{
if cfg!(debug_assertions) {
eprintln!("saving project");
}
false
}
false
}
/// Saves the project into `path`.
fn save_as(&self, path: String) -> bool
{
if cfg!(debug_assertions) {
eprintln!("saving project as {}", path);
}
/// Saves the project into `path`.
fn save_as(&self, path: String) -> bool
{
if cfg!(debug_assertions) {
eprintln!("saving project as {}", path);
}
false
}
false
}
/// Returns `true` if the file has been modified from its original state.
fn dirty(&self) -> bool {self.dirty}
/// Returns `true` if the file has been modified from its original state.
fn dirty(&self) -> bool {self.dirty}
fn set_dirty(&mut self, dirty: bool) {self.dirty = dirty;}
fn set_dirty(&mut self, dirty: bool) {self.dirty = dirty;}
fn deselect(&mut self) {self.selected = None;}
fn deselect(&mut self) {self.selected = None;}
fn select(&mut self, index: u16)
{
if cfg!(debug_assertions) {
eprintln!("selecting map {}", index);
}
fn select(&mut self, index: u16)
{
if cfg!(debug_assertions) {
eprintln!("selecting map {}", index);
}
self.selected = Some(index);
}
self.selected = Some(index);
}
}
impl Drop for IMapModel
{
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop IMapModel");
}
}
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop IMapModel");
}
}
}
pub struct IMapModel {
emit: IMapModelEmitter,
map: EntryDataMap,
selected: Option<u16>,
dirty: bool,
emit: IMapModelEmitter,
map: EntryDataMap,
selected: Option<u16>,
dirty: bool,
}
// EOF

View File

@ -4,32 +4,32 @@ use super::qobj::*;
impl IMapViewTrait for IMapView
{
/// Returns a new `IMapView` instance.
fn new(emit: IMapViewEmitter) -> Self
{
if cfg!(debug_assertions) {
eprintln!("new IMapView");
}
/// Returns a new `IMapView` instance.
fn new(emit: IMapViewEmitter) -> Self
{
if cfg!(debug_assertions) {
eprintln!("new IMapView");
}
Self{emit}
}
Self{emit}
}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut IMapViewEmitter {&mut self.emit}
/// Returns the emitter of `self`.
fn emit(&mut self) -> &mut IMapViewEmitter {&mut self.emit}
}
impl Drop for IMapView
{
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop IMapView");
}
}
fn drop(&mut self)
{
if cfg!(debug_assertions) {
eprintln!("drop IMapView");
}
}
}
pub struct IMapView {
emit: IMapViewEmitter,
emit: IMapViewEmitter,
}
// EOF

View File

@ -5,24 +5,24 @@ mod gui;
mod meta;
extern "C" {
fn main_cc(app_name: *mut ffi::c_char);
fn main_cc(app_name: *mut ffi::c_char);
}
fn main() -> ResultS<()>
{
if cfg!(debug_assertions) {
eprintln!("rust entry");
}
if cfg!(debug_assertions) {
eprintln!("rust entry");
}
let mut args = std::env::args();
let app_name = args.next().ok_or(err_msg("bad launch name"))?;
let app_name = ffi::CString::new(app_name)?;
let mut args = std::env::args();
let app_name = args.next().ok_or(err_msg("bad launch name"))?;
let app_name = ffi::CString::new(app_name)?;
unsafe {
main_cc(app_name.into_raw());
}
unsafe {
main_cc(app_name.into_raw());
}
Ok(())
Ok(())
}
// EOF

View File

@ -3,23 +3,23 @@
use maraiah::{ffi, meta};
macro_rules! meta_str {
($($name:ident = $e:expr;)*) => {
$(
#[no_mangle]
pub extern "C" fn $name() -> ffi::NT
{
$e
}
)*
}
($($name:ident = $e:expr;)*) => {
$(
#[no_mangle]
pub extern "C" fn $name() -> ffi::NT
{
$e
}
)*
}
}
meta_str! {
tychoAuthors = meta::ffi::authors();
tychoHomepage = meta::ffi::homepage();
tychoLicenseText = meta::ffi::license_text();
tychoRepository = meta::ffi::repository();
tychoVersion = meta::ffi::version();
tychoAuthors = meta::ffi::authors();
tychoHomepage = meta::ffi::homepage();
tychoLicenseText = meta::ffi::license_text();
tychoRepository = meta::ffi::repository();
tychoVersion = meta::ffi::version();
}
// EOF