spaces->tabs
parent
8354207c75
commit
e3eaeeec66
60
bundle.sh
60
bundle.sh
|
@ -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}
|
||||
|
|
176
leela/main.rs
176
leela/main.rs
|
@ -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
|
||||
|
|
520
maraiah/bin.rs
520
maraiah/bin.rs
|
@ -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.
|
||||
|
|
196
maraiah/bit.rs
196
maraiah/bit.rs
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
152
maraiah/cenum.rs
152
maraiah/cenum.rs
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
586
maraiah/defl.rs
586
maraiah/defl.rs
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
166
maraiah/err.rs
166
maraiah/err.rs
|
@ -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)]
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
1028
maraiah/fixed.rs
1028
maraiah/fixed.rs
File diff suppressed because it is too large
Load Diff
230
maraiah/image.rs
230
maraiah/image.rs
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: <fn::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: <fn::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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
120
maraiah/sound.rs
120
maraiah/sound.rs
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
198
maraiah/text.rs
198
maraiah/text.rs
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)}
|
||||
]
|
||||
|
|
|
@ -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
|
||||
},
|
||||
]
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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 )
|
||||
]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
146
tests/map.rs
146
tests/map.rs
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
16
tests/shp.rs
16
tests/shp.rs
|
@ -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
|
||||
|
|
12
tests/snd.rs
12
tests/snd.rs
|
@ -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
|
||||
|
|
|
@ -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>"
|
||||
|
|
|
@ -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": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
146
tycho/cc/menu.cc
146
tycho/cc/menu.cc
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
116
tycho/cc/tycho.h
116
tycho/cc/tycho.h
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue