spaces->tabs
parent
8354207c75
commit
e3eaeeec66
60
bundle.sh
60
bundle.sh
|
@ -5,34 +5,34 @@ err_bad_arg=1
|
||||||
err_bad_run=2
|
err_bad_run=2
|
||||||
|
|
||||||
rm_if() {
|
rm_if() {
|
||||||
if [[ -d $1 ]];
|
if [[ -d $1 ]];
|
||||||
then
|
then
|
||||||
rm -rf "$1" && echo "removed dir $1"
|
rm -rf "$1" && echo "removed dir $1"
|
||||||
elif [[ -f $1 ]]
|
elif [[ -f $1 ]]
|
||||||
then
|
then
|
||||||
rm -f "$1" && echo "removed file $1"
|
rm -f "$1" && echo "removed file $1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
perish() {
|
perish() {
|
||||||
rm_if "${tmpdir}"
|
rm_if "${tmpdir}"
|
||||||
exit "$1"
|
exit "$1"
|
||||||
}
|
}
|
||||||
err() {
|
err() {
|
||||||
echo "error, dropping build"
|
echo "error, dropping build"
|
||||||
rm_if "${appdir}"
|
rm_if "${appdir}"
|
||||||
rm_if "${dmg}"
|
rm_if "${dmg}"
|
||||||
perish $1
|
perish $1
|
||||||
}
|
}
|
||||||
:() {
|
:() {
|
||||||
echo "$@"
|
echo "$@"
|
||||||
echo
|
echo
|
||||||
eval "$@" || err ${err_bad_run}
|
eval "$@" || err ${err_bad_run}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare -A icon_names=(
|
declare -A icon_names=(
|
||||||
[Tycho]="resources/color/pfhor-hand.png"
|
[Tycho]="resources/color/pfhor-hand.png"
|
||||||
)
|
)
|
||||||
|
|
||||||
name=$1
|
name=$1
|
||||||
|
@ -40,14 +40,14 @@ exe=$2
|
||||||
|
|
||||||
if [[ ! $name ]]
|
if [[ ! $name ]]
|
||||||
then
|
then
|
||||||
echo "program name needed (available: Tycho)"
|
echo "program name needed (available: Tycho)"
|
||||||
err ${err_bad_arg}
|
err ${err_bad_arg}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! $exe ]]
|
if [[ ! $exe ]]
|
||||||
then
|
then
|
||||||
echo "full path to executable required (ex. '$0 $name ~/bin/maraiah-tycho')"
|
echo "full path to executable required (ex. '$0 $name ~/bin/maraiah-tycho')"
|
||||||
err ${err_bad_arg}
|
err ${err_bad_arg}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
app=${name}.app
|
app=${name}.app
|
||||||
|
@ -89,25 +89,25 @@ dmg=${exedir}/${name}.dmg
|
||||||
|
|
||||||
while IFS= read -r lnk
|
while IFS= read -r lnk
|
||||||
do
|
do
|
||||||
lnk=$(dirname "${lnk}")
|
lnk=$(dirname "${lnk}")
|
||||||
: cp -r "${lnk}" "${appdir}/Contents/Frameworks"
|
: cp -r "${lnk}" "${appdir}/Contents/Frameworks"
|
||||||
done < "${exedir}"/build/maraiah-tycho-*/out/etc/link.txt
|
done < "${exedir}"/build/maraiah-tycho-*/out/etc/link.txt
|
||||||
|
|
||||||
echo "success: bundle written to ${appdir}"
|
echo "success: bundle written to ${appdir}"
|
||||||
|
|
||||||
if [[ ! "$NO_DMG" ]]
|
if [[ ! "$NO_DMG" ]]
|
||||||
then
|
then
|
||||||
echo "creating the disk image..."
|
echo "creating the disk image..."
|
||||||
|
|
||||||
: rm_if "${dmg}"
|
: rm_if "${dmg}"
|
||||||
|
|
||||||
: mkdir -p "${diskdir}"
|
: mkdir -p "${diskdir}"
|
||||||
: cp -r "${appdir}" "${diskdir}"
|
: cp -r "${appdir}" "${diskdir}"
|
||||||
: cp "${srcdir}/resources/Image.DS_Store" "${diskdir}/.DS_Store"
|
: cp "${srcdir}/resources/Image.DS_Store" "${diskdir}/.DS_Store"
|
||||||
: ln -s /Applications "${diskdir}"
|
: ln -s /Applications "${diskdir}"
|
||||||
: hdiutil create -volname "${name}" -srcfolder "${diskdir}" "${dmg}"
|
: hdiutil create -volname "${name}" -srcfolder "${diskdir}" "${dmg}"
|
||||||
|
|
||||||
echo "success: dmg written to ${dmg}"
|
echo "success: dmg written to ${dmg}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
perish ${err_ok}
|
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>
|
fn open(path: &str) -> ResultS<io::BufReader>
|
||||||
{
|
{
|
||||||
let fp = fs::File::open(path)?;
|
let fp = fs::File::open(path)?;
|
||||||
Ok(io::BufReader::new(fp))
|
Ok(io::BufReader::new(fp))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file_read<T, F>(path: &str, f: F) -> ResultS<T>
|
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 mm = open(path)?;
|
||||||
let bp = &mm[machdr::try_mac_header(&mm)..];
|
let bp = &mm[machdr::try_mac_header(&mm)..];
|
||||||
|
|
||||||
f(bp)
|
f(bp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists(path: String) -> Result<(), String>
|
fn exists(path: String) -> Result<(), String>
|
||||||
{
|
{
|
||||||
match std::fs::metadata(path) {
|
match std::fs::metadata(path) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => Err(e.to_string()),
|
Err(e) => Err(e.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each_value<F>(opt: &clap::ArgMatches<'_>,
|
fn each_value<F>(opt: &clap::ArgMatches<'_>,
|
||||||
name: &str,
|
name: &str,
|
||||||
mut f: F)
|
mut f: F) -> ResultS<()>
|
||||||
-> ResultS<()>
|
where F: FnMut(&str) -> ResultS<()>
|
||||||
where F: FnMut(&str) -> ResultS<()>
|
|
||||||
{
|
{
|
||||||
if let Some(values) = opt.values_of(name) {
|
if let Some(values) = opt.values_of(name) {
|
||||||
for value in values {
|
for value in values {
|
||||||
f(value)?;
|
f(value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dbg_info(data: impl std::fmt::Debug)
|
fn dbg_info(data: impl std::fmt::Debug)
|
||||||
{
|
{
|
||||||
println!("{:#?}", data);
|
println!("{:#?}", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_map(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
|
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") {
|
if let Some(opt_cnks) = opt.values_of("chunks") {
|
||||||
for typ in opt_cnks {
|
for typ in opt_cnks {
|
||||||
cnks.insert(typ);
|
cnks.insert(typ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_shp(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
|
fn dump_shp(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
|
||||||
{
|
{
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_snd(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
|
fn dump_snd(opt: &clap::ArgMatches<'_>, f: &str) -> ResultS<()>
|
||||||
{
|
{
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_data_c(_opt: &clap::ArgMatches<'_>) -> ResultS<()>
|
fn sub_data_c(_opt: &clap::ArgMatches<'_>) -> ResultS<()>
|
||||||
{
|
{
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_dump_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
|
fn sub_dump_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
|
||||||
{
|
{
|
||||||
each_value(opt, "map", |f| dump_map(opt, f))?;
|
each_value(opt, "map", |f| dump_map(opt, f))?;
|
||||||
each_value(opt, "shp", |f| dump_shp(opt, f))?;
|
each_value(opt, "shp", |f| dump_shp(opt, f))?;
|
||||||
each_value(opt, "snd", |f| dump_snd(opt, f))?;
|
each_value(opt, "snd", |f| dump_snd(opt, f))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_info_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
|
fn sub_info_c(opt: &clap::ArgMatches<'_>) -> ResultS<()>
|
||||||
{
|
{
|
||||||
each_value(opt, "map", |f| Ok(dbg_info(file_read(f, map::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, "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, "snd", |f| Ok(dbg_info(file_read(f, snd::read)?)))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn main() -> ResultS<()>
|
fn main() -> ResultS<()>
|
||||||
{
|
{
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
let inp = include_bytes!("../tests/data/map/Test.in");
|
let inp = include_bytes!("../tests/data/map/Test.in");
|
||||||
let mut rd = std::io::BufReader::new(&inp[..]);
|
let mut rd = std::io::BufReader::new(&inp[..]);
|
||||||
|
|
||||||
let mp = map::head::read(&mut rd).unwrap();
|
let mp = map::head::read(&mut rd).unwrap();
|
||||||
let en = map::entr::read_all(&mp).unwrap();
|
let en = map::entr::read_all(&mp).unwrap();
|
||||||
let ed = map::data::read_all(mp.head(), &en).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! {
|
let sub_data = clap_app! {
|
||||||
@subcommand data =>
|
@subcommand data =>
|
||||||
(about: "Dumps data into a discrete folder/YAML format")
|
(about: "Dumps data into a discrete folder/YAML format")
|
||||||
};
|
};
|
||||||
|
|
||||||
let sub_dump = clap_app! {
|
let sub_dump = clap_app! {
|
||||||
@subcommand dump =>
|
@subcommand dump =>
|
||||||
(about: "Dumps particular parts of data")
|
(about: "Dumps particular parts of data")
|
||||||
(@arg chunks: -c --chunks [name]... "Dumps named chunks from an entry")
|
(@arg chunks: -c --chunks [name]... "Dumps named chunks from an entry")
|
||||||
(@group files =>
|
(@group files =>
|
||||||
(@attributes +required +multiple)
|
(@attributes +required +multiple)
|
||||||
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
||||||
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
||||||
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
|
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
|
||||||
};
|
};
|
||||||
|
|
||||||
let sub_info = clap_app! {
|
let sub_info = clap_app! {
|
||||||
@subcommand info =>
|
@subcommand info =>
|
||||||
(about: "Outputs debug info")
|
(about: "Outputs debug info")
|
||||||
(@group files =>
|
(@group files =>
|
||||||
(@attributes +required +multiple)
|
(@attributes +required +multiple)
|
||||||
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
(@arg map: -m --map [file]... {exists} "Loads Map files")
|
||||||
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
(@arg shp: -s --shp [file]... {exists} "Loads Shapes files")
|
||||||
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
|
(@arg snd: -n --snd [file]... {exists} "Loads Sounds files"))
|
||||||
};
|
};
|
||||||
|
|
||||||
let opt = clap_app! {
|
let opt = clap_app! {
|
||||||
(env!("CARGO_PKG_NAME")) =>
|
(env!("CARGO_PKG_NAME")) =>
|
||||||
(version: maraiah::meta::version())
|
(version: maraiah::meta::version())
|
||||||
(author: maraiah::meta::authors().replace(':', ", "))
|
(author: maraiah::meta::authors().replace(':', ", "))
|
||||||
(about: maraiah::meta::description())
|
(about: maraiah::meta::description())
|
||||||
(setting: clap::AppSettings::SubcommandRequiredElseHelp)
|
(setting: clap::AppSettings::SubcommandRequiredElseHelp)
|
||||||
(subcommand: sub_data)
|
(subcommand: sub_data)
|
||||||
(subcommand: sub_dump)
|
(subcommand: sub_dump)
|
||||||
(subcommand: sub_info)
|
(subcommand: sub_info)
|
||||||
};
|
};
|
||||||
|
|
||||||
let opt = opt.get_matches();
|
let opt = opt.get_matches();
|
||||||
|
|
||||||
match opt.subcommand() {
|
match opt.subcommand() {
|
||||||
("data", Some(opt)) => sub_data_c(opt)?,
|
("data", Some(opt)) => sub_data_c(opt)?,
|
||||||
("dump", Some(opt)) => sub_dump_c(opt)?,
|
("dump", Some(opt)) => sub_dump_c(opt)?,
|
||||||
("info", Some(opt)) => sub_info_c(opt)?,
|
("info", Some(opt)) => sub_info_c(opt)?,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
520
maraiah/bin.rs
520
maraiah/bin.rs
|
@ -6,136 +6,136 @@ use std::{convert::{TryFrom, TryInto}, fmt, num::NonZeroU16};
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! rd_impl {
|
macro_rules! rd_impl {
|
||||||
// worker, creates let statement for 16 bit numbers
|
// worker, creates let statement for 16 bit numbers
|
||||||
(W $b:expr, $pth:path, $nam:ident, $n:expr) => {
|
(W $b:expr, $pth:path, $nam:ident, $n:expr) => {
|
||||||
let $nam = $pth([$b[$n], $b[$n + 1]]);
|
let $nam = $pth([$b[$n], $b[$n + 1]]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// worker, creates let statement for 32 bit numbers
|
// worker, creates let statement for 32 bit numbers
|
||||||
(D $b:expr, $pth:path, $nam:ident, $n:expr) => {
|
(D $b:expr, $pth:path, $nam:ident, $n:expr) => {
|
||||||
let $nam = $pth([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]);
|
let $nam = $pth([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// big endian, u16
|
// big endian, u16
|
||||||
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
|
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
|
||||||
$crate::rd_impl!(W $b, u16::from_be_bytes, $nam, $n + $at);
|
$crate::rd_impl!(W $b, u16::from_be_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// big endian, i16
|
// big endian, i16
|
||||||
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
|
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
|
||||||
$crate::rd_impl!(W $b, i16::from_be_bytes, $nam, $n + $at);
|
$crate::rd_impl!(W $b, i16::from_be_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// big endian, u32
|
// big endian, u32
|
||||||
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
|
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
|
||||||
$crate::rd_impl!(D $b, u32::from_be_bytes, $nam, $n + $at);
|
$crate::rd_impl!(D $b, u32::from_be_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// big endian, i32
|
// big endian, i32
|
||||||
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
|
(BIG, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
|
||||||
$crate::rd_impl!(D $b, i32::from_be_bytes, $nam, $n + $at);
|
$crate::rd_impl!(D $b, i32::from_be_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// little endian, u16
|
// little endian, u16
|
||||||
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
|
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u16) => {
|
||||||
$crate::rd_impl!(W $b, u16::from_le_bytes, $nam, $n + $at);
|
$crate::rd_impl!(W $b, u16::from_le_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// little endian, i16
|
// little endian, i16
|
||||||
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
|
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i16) => {
|
||||||
$crate::rd_impl!(W $b, i16::from_le_bytes, $nam, $n + $at);
|
$crate::rd_impl!(W $b, i16::from_le_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// little endian, u32
|
// little endian, u32
|
||||||
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
|
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, u32) => {
|
||||||
$crate::rd_impl!(D $b, u32::from_le_bytes, $nam, $n + $at);
|
$crate::rd_impl!(D $b, u32::from_le_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// little endian, i32
|
// little endian, i32
|
||||||
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
|
(LITTLE, $b:expr, $at:expr, $n:expr; $nam:ident, i32) => {
|
||||||
$crate::rd_impl!(D $b, i32::from_le_bytes, $nam, $n + $at);
|
$crate::rd_impl!(D $b, i32::from_le_bytes, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, Angle
|
// either endianness, Angle
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Angle) => {
|
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Angle) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
||||||
let $nam = $crate::fixed::Angle::from_bits($nam);
|
let $nam = $crate::fixed::Angle::from_bits($nam);
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, Fixed
|
// either endianness, Fixed
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Fixed) => {
|
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Fixed) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
|
||||||
let $nam = $crate::fixed::Fixed::from_bits($nam);
|
let $nam = $crate::fixed::Fixed::from_bits($nam);
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, Unit
|
// either endianness, Unit
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Unit) => {
|
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Unit) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
||||||
let $nam = $crate::fixed::Unit::from_bits($nam);
|
let $nam = $crate::fixed::Unit::from_bits($nam);
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, OptU16
|
// either endianness, OptU16
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, OptU16) => {
|
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, OptU16) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
||||||
let $nam = $crate::bin::OptU16::from($nam);
|
let $nam = $crate::bin::OptU16::from($nam);
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, u16 -> usize
|
// either endianness, u16 -> usize
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u16) => {
|
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u16) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, u16);
|
||||||
let $nam = usize::from($nam);
|
let $nam = usize::from($nam);
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, u32 -> usize
|
// either endianness, u32 -> usize
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u32) => {
|
($e:ident, $b:expr, $at:expr, $n:expr; $nam:ident, usize, u32) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, u32);
|
||||||
let $nam = $crate::bin::usize_from_u32($nam);
|
let $nam = $crate::bin::usize_from_u32($nam);
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, enum type with TryFrom
|
// either endianness, enum type with TryFrom
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr;
|
($e:ident, $b:expr, $at:expr, $n:expr;
|
||||||
$nam:ident, enum, $et:ident$(::$etc:ident)*, $t:ident) => {
|
$nam:ident, enum, $et:ident$(::$etc:ident)*, $t:ident) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
|
||||||
let $nam: $et$(::$etc)* = std::convert::TryFrom::try_from($nam)?;
|
let $nam: $et$(::$etc)* = std::convert::TryFrom::try_from($nam)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
// either endianness, bitflag type
|
// either endianness, bitflag type
|
||||||
($e:ident, $b:expr, $at:expr, $n:expr;
|
($e:ident, $b:expr, $at:expr, $n:expr;
|
||||||
$nam:ident, flag, $ft:ident$(::$ftc:ident)*, $t:ident) => {
|
$nam:ident, flag, $ft:ident$(::$ftc:ident)*, $t:ident) => {
|
||||||
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
|
$crate::rd_impl!($e, $b, $at, $n; $nam, $t);
|
||||||
let $nam = flag_ok!($ft$(::$ftc)*, $nam)?;
|
let $nam = flag_ok!($ft$(::$ftc)*, $nam)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
// no endianness, u8
|
// no endianness, u8
|
||||||
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, u8) => {
|
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, u8) => {
|
||||||
let $nam = $b[$n + $at];
|
let $nam = $b[$n + $at];
|
||||||
};
|
};
|
||||||
|
|
||||||
// no endianness, i8
|
// no endianness, i8
|
||||||
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, i8) => {
|
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, i8) => {
|
||||||
let $nam = $b[$n + $at] as i8;
|
let $nam = $b[$n + $at] as i8;
|
||||||
};
|
};
|
||||||
|
|
||||||
// no endianness, [u8]
|
// no endianness, [u8]
|
||||||
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, u8) => {
|
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, u8) => {
|
||||||
let $nam = &$b[$n + $at..$n + $at + $rn];
|
let $nam = &$b[$n + $at..$n + $at + $rn];
|
||||||
};
|
};
|
||||||
|
|
||||||
// no endianness, Ident
|
// no endianness, Ident
|
||||||
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Ident) => {
|
($_:ident, $b:expr, $at:expr, $n:expr; $nam:ident, Ident) => {
|
||||||
$crate::rd_impl!(D $b, Ident, $nam, $n + $at);
|
$crate::rd_impl!(D $b, Ident, $nam, $n + $at);
|
||||||
};
|
};
|
||||||
|
|
||||||
// no endianness, fn([u8]) -> T
|
// no endianness, fn([u8]) -> T
|
||||||
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr;
|
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr;
|
||||||
$nam:ident, no_try, $f:expr) => {
|
$nam:ident, no_try, $f:expr) => {
|
||||||
let $nam = $f(&$b[$n + $at..$n + $at + $rn]);
|
let $nam = $f(&$b[$n + $at..$n + $at + $rn]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// no endianness, fn([u8]) -> Result<T>
|
// no endianness, fn([u8]) -> Result<T>
|
||||||
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, $f:expr) => {
|
($_:ident, $b:expr, $at:expr, $n:expr; $rn:expr; $nam:ident, $f:expr) => {
|
||||||
let $nam = $f(&$b[$n + $at..$n + $at + $rn])?;
|
let $nam = $f(&$b[$n + $at..$n + $at + $rn])?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads structured data from a byte slice.
|
/// Reads structured data from a byte slice.
|
||||||
|
@ -201,12 +201,12 @@ macro_rules! rd_impl {
|
||||||
/// let buffer = &[4, 0, 2, 0, 0, 0, 6];
|
/// let buffer = &[4, 0, 2, 0, 0, 0, 6];
|
||||||
///
|
///
|
||||||
/// read_data! {
|
/// read_data! {
|
||||||
/// endian: LITTLE, buf: buffer, size: 7, start: 0, data {
|
/// endian: LITTLE, buf: buffer, size: 7, start: 0, data {
|
||||||
/// let four = u16[0];
|
/// let four = u16[0];
|
||||||
/// let two = u32[2];
|
/// let two = u32[2];
|
||||||
/// let six = u8[6];
|
/// let six = u8[6];
|
||||||
/// let byte = u8[2; 4];
|
/// let byte = u8[2; 4];
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// assert_eq!(four, 4_u16);
|
/// assert_eq!(four, 4_u16);
|
||||||
|
@ -218,16 +218,16 @@ macro_rules! rd_impl {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! read_data {
|
macro_rules! read_data {
|
||||||
(
|
(
|
||||||
endian: $e:ident, buf: $b:expr, size: $sz:expr, start: $at:expr, 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)?]
|
$(let $nam:ident = $t:ident$(::$tc:ident)*[$n:expr $(; $rn:expr)?]
|
||||||
$($ex:ident$(::$exc:ident)*)*;)*
|
$($ex:ident$(::$exc:ident)*)*;)*
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
$crate::bin::check_data($b, $at + $sz)?;
|
$crate::bin::check_data($b, $at + $sz)?;
|
||||||
$($crate::rd_impl!($e, $b, $at, $n;
|
$($crate::rd_impl!($e, $b, $at, $n;
|
||||||
$($rn;)? $nam, $($ex$(::$exc)*,)* $t$(::$tc)*);)*
|
$($rn;)? $nam, $($ex$(::$exc)*,)* $t$(::$tc)*);)*
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if there is enough data in `b`.
|
/// Checks if there is enough data in `b`.
|
||||||
|
@ -238,11 +238,11 @@ macro_rules! read_data {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn check_data<T>(b: &[T], sz: usize) -> ResultS<()>
|
pub fn check_data<T>(b: &[T], sz: usize) -> ResultS<()>
|
||||||
{
|
{
|
||||||
if b.len() < sz {
|
if b.len() < sz {
|
||||||
Err(err_msg("not enough data"))
|
Err(err_msg("not enough data"))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Casts a `u32` to a `usize`.
|
/// Casts a `u32` to a `usize`.
|
||||||
|
@ -262,7 +262,7 @@ pub fn check_data<T>(b: &[T], sz: usize) -> ResultS<()>
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn usize_from_u32(n: u32) -> usize
|
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.
|
/// Creates an `Ident` from a slice.
|
||||||
|
@ -281,7 +281,7 @@ pub fn usize_from_u32(n: u32) -> usize
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn ident(b: &[u8]) -> Ident
|
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.
|
/// Applies `u32::from_be_bytes` to a slice.
|
||||||
|
@ -300,7 +300,7 @@ pub fn ident(b: &[u8]) -> Ident
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn u32b(b: &[u8]) -> u32
|
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.
|
/// Applies `u16::from_be_bytes` to a slice.
|
||||||
|
@ -319,7 +319,7 @@ pub fn u32b(b: &[u8]) -> u32
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn u16b(b: &[u8]) -> u16
|
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.
|
/// Applies `i32::from_be_bytes` to a slice.
|
||||||
|
@ -338,7 +338,7 @@ pub fn u16b(b: &[u8]) -> u16
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn i32b(b: &[u8]) -> i32
|
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.
|
/// Applies `i16::from_be_bytes` to a slice.
|
||||||
|
@ -357,7 +357,7 @@ pub fn i32b(b: &[u8]) -> i32
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn i16b(b: &[u8]) -> i16
|
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.
|
/// 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]);
|
/// 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>>
|
pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
|
||||||
where T: Sized,
|
where T: Sized,
|
||||||
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
||||||
{
|
{
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
while p < b.len() {
|
while p < b.len() {
|
||||||
let (r, s) = read(&b[p..])?;
|
let (r, s) = read(&b[p..])?;
|
||||||
v.push(r);
|
v.push(r);
|
||||||
p += s;
|
p += s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies a read function a number of times over a slice.
|
/// 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],
|
pub fn rd_array_num<T, F>(b: &[u8],
|
||||||
n: usize,
|
n: usize,
|
||||||
read: F) -> ResultS<(Vec<T>, usize)>
|
read: F) -> ResultS<(Vec<T>, usize)>
|
||||||
where T: Sized,
|
where T: Sized,
|
||||||
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
||||||
{
|
{
|
||||||
let mut v = Vec::with_capacity(n);
|
let mut v = Vec::with_capacity(n);
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
for _ in 0..n {
|
for _ in 0..n {
|
||||||
let (r, s) = read(&b[p..])?;
|
let (r, s) = read(&b[p..])?;
|
||||||
v.push(r);
|
v.push(r);
|
||||||
p += s;
|
p += s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((v, p))
|
Ok((v, p))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies a read function over a slice with an offset table.
|
/// 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,
|
mut p: usize,
|
||||||
num: usize,
|
num: usize,
|
||||||
read: F) -> ResultS<Vec<T>>
|
read: F) -> ResultS<Vec<T>>
|
||||||
where T: Sized,
|
where T: Sized,
|
||||||
F: Fn(&[u8]) -> ResultS<T>
|
F: Fn(&[u8]) -> ResultS<T>
|
||||||
{
|
{
|
||||||
let mut v = Vec::with_capacity(num);
|
let mut v = Vec::with_capacity(num);
|
||||||
|
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let ofs = usize_from_u32(u32b(&b[p..p + 4]));
|
let ofs = usize_from_u32(u32b(&b[p..p + 4]));
|
||||||
check_data(b, ofs)?;
|
check_data(b, ofs)?;
|
||||||
v.push(read(&b[ofs..])?);
|
v.push(read(&b[ofs..])?);
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u16> for OptU16
|
impl From<u16> for OptU16
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(n: u16) -> Self
|
fn from(n: u16) -> Self
|
||||||
{
|
{
|
||||||
if n == u16::max_value() {
|
if n == u16::max_value() {
|
||||||
Self(None)
|
Self(None)
|
||||||
} else {
|
} else {
|
||||||
Self(NonZeroU16::new(n + 1))
|
Self(NonZeroU16::new(n + 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<u16> for OptU16
|
impl Into<u16> for OptU16
|
||||||
{
|
{
|
||||||
/// Returns the `u16` representation.
|
/// Returns the `u16` representation.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use maraiah::bin::OptU16;
|
/// use maraiah::bin::OptU16;
|
||||||
///
|
///
|
||||||
/// let u16_max = u16::max_value();
|
/// let u16_max = u16::max_value();
|
||||||
///
|
///
|
||||||
/// // These type annotations are necessary.
|
/// // 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(500u16)), 500u16);
|
||||||
/// assert_eq!(<OptU16 as Into<u16>>::into(OptU16::from(u16_max)), u16_max);
|
/// assert_eq!(<OptU16 as Into<u16>>::into(OptU16::from(u16_max)), u16_max);
|
||||||
/// assert_eq!(<OptU16 as Into<u16>>::into(OptU16::from(0u16)), 0u16);
|
/// assert_eq!(<OptU16 as Into<u16>>::into(OptU16::from(0u16)), 0u16);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self) -> u16
|
fn into(self) -> u16
|
||||||
{
|
{
|
||||||
match self.0 {
|
match self.0 {
|
||||||
None => u16::max_value(),
|
None => u16::max_value(),
|
||||||
Some(n) => n.get() - 1,
|
Some(n) => n.get() - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OptU16
|
impl OptU16
|
||||||
{
|
{
|
||||||
/// Creates an `OptU16` representing `None`.
|
/// Creates an `OptU16` representing `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use maraiah::bin::OptU16;
|
/// use maraiah::bin::OptU16;
|
||||||
///
|
///
|
||||||
/// assert_eq!(OptU16::none(), OptU16::from(u16::max_value()));
|
/// assert_eq!(OptU16::none(), OptU16::from(u16::max_value()));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn none() -> Self {Self(None)}
|
pub const fn none() -> Self {Self(None)}
|
||||||
|
|
||||||
/// Returns the `Option` representation.
|
/// Returns the `Option` representation.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use maraiah::bin::OptU16;
|
/// use maraiah::bin::OptU16;
|
||||||
///
|
///
|
||||||
/// assert_eq!(OptU16::from(500u16).get(), Some(500u16));
|
/// assert_eq!(OptU16::from(500u16).get(), Some(500u16));
|
||||||
/// assert_eq!(OptU16::from(u16::max_value()).get(), None);
|
/// assert_eq!(OptU16::from(u16::max_value()).get(), None);
|
||||||
/// assert_eq!(OptU16::from(0u16).get(), Some(0u16));
|
/// assert_eq!(OptU16::from(0u16).get(), Some(0u16));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(self) -> Option<u16>
|
pub fn get(self) -> Option<u16>
|
||||||
{
|
{
|
||||||
match self.0 {
|
match self.0 {
|
||||||
None => None,
|
None => None,
|
||||||
Some(n) => Some(n.get() - 1),
|
Some(n) => Some(n.get() - 1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the memory representation of this integer as a byte array
|
/// Return the memory representation of this integer as a byte array
|
||||||
/// in big-endian (network) byte order.
|
/// in big-endian (network) byte order.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_be_bytes(self) -> [u8; 2]
|
pub fn to_be_bytes(self) -> [u8; 2]
|
||||||
{
|
{
|
||||||
<Self as Into<u16>>::into(self).to_be_bytes()
|
<Self as Into<u16>>::into(self).to_be_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the memory representation of this integer as a byte array
|
/// Return the memory representation of this integer as a byte array
|
||||||
/// in little-endian byte order.
|
/// in little-endian byte order.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_le_bytes(self) -> [u8; 2]
|
pub fn to_le_bytes(self) -> [u8; 2]
|
||||||
{
|
{
|
||||||
<Self as Into<u16>>::into(self).to_le_bytes()
|
<Self as Into<u16>>::into(self).to_le_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for OptU16
|
impl fmt::Display for OptU16
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
{
|
{
|
||||||
match self.get() {
|
match self.get() {
|
||||||
None => write!(f, "None"),
|
None => write!(f, "None"),
|
||||||
Some(n) => write!(f, "Some({})", n),
|
Some(n) => write!(f, "Some({})", n),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for OptU16
|
impl fmt::Debug for OptU16
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
{
|
{
|
||||||
match self.get() {
|
match self.get() {
|
||||||
None => write!(f, "OptU16::none()"),
|
None => write!(f, "OptU16::none()"),
|
||||||
Some(n) => write!(f, "OptU16::from({})", n),
|
Some(n) => write!(f, "OptU16::from({})", n),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<[u8; 4]> for Ident
|
impl PartialEq<[u8; 4]> for Ident
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, o: &[u8; 4]) -> bool {self.0 == *o}
|
fn eq(&self, o: &[u8; 4]) -> bool {self.0 == *o}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PartialEq<[u8; 4]> for &'a Ident
|
impl<'a> PartialEq<[u8; 4]> for &'a Ident
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, o: &[u8; 4]) -> bool {PartialEq::eq(*self, o)}
|
fn eq(&self, o: &[u8; 4]) -> bool {PartialEq::eq(*self, o)}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PartialEq<&'a [u8; 4]> for Ident
|
impl<'a> PartialEq<&'a [u8; 4]> for Ident
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, o: &&'a [u8; 4]) -> bool {PartialEq::eq(self, *o)}
|
fn eq(&self, o: &&'a [u8; 4]) -> bool {PartialEq::eq(self, *o)}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A four-character-code identifier.
|
/// 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`.
|
/// `(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>
|
pub fn read_bits_b(b: &[u8], cr_bit: usize, width: u8) -> ResultS<u64>
|
||||||
{
|
{
|
||||||
if width == 0 {
|
if width == 0 {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if width > 64 {
|
if width > 64 {
|
||||||
bail!("invalid number of bits");
|
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() {
|
if last >= b.len() {
|
||||||
bail!("not enough data");
|
bail!("not enough data");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut byte_ptr = cr_bit / 8;
|
let mut byte_ptr = cr_bit / 8;
|
||||||
let mut bits_ptr = cr_bit % 8;
|
let mut bits_ptr = cr_bit % 8;
|
||||||
|
|
||||||
let mut res = 0;
|
let mut res = 0;
|
||||||
|
|
||||||
for _ in 0..width {
|
for _ in 0..width {
|
||||||
res <<= 1;
|
res <<= 1;
|
||||||
|
|
||||||
if b[byte_ptr] & (1 << bits_ptr) != 0 {
|
if b[byte_ptr] & (1 << bits_ptr) != 0 {
|
||||||
res |= 1;
|
res |= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bits_ptr += 1;
|
bits_ptr += 1;
|
||||||
|
|
||||||
if bits_ptr > 7 {
|
if bits_ptr > 7 {
|
||||||
bits_ptr = 0;
|
bits_ptr = 0;
|
||||||
byte_ptr += 1;
|
byte_ptr += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The same as `read_bits_b`, but least-significant bit first.
|
/// 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>
|
pub fn read_bits_l(b: &[u8], cr_bit: usize, width: u8) -> ResultS<u64>
|
||||||
{
|
{
|
||||||
if width == 0 {
|
if width == 0 {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
} else {
|
} else {
|
||||||
let res = read_bits_b(b, cr_bit, width)?;
|
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
|
// FIXME: change this to u64::reverse_bits when stabilized
|
||||||
const fn reverse_bits(v: u64) -> u64
|
const fn reverse_bits(v: u64) -> u64
|
||||||
{
|
{
|
||||||
let v = v >> 1 & 0x5555_5555_5555_5555 | ((v & 0x5555_5555_5555_5555) << 1);
|
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 >> 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);
|
let v = v >> 4 & 0x0F0F_0F0F_0F0F_0F0F | ((v & 0x0F0F_0F0F_0F0F_0F0F) << 4);
|
||||||
v.swap_bytes()
|
v.swap_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bit_tests()
|
fn bit_tests()
|
||||||
{
|
{
|
||||||
const INPUT: &[u8] = &[0b01100101, 0b10101010, 0b00010000, 0b00000000,
|
const INPUT: &[u8] = &[0b01100101, 0b10101010, 0b00010000, 0b00000000,
|
||||||
0b11111111, 0b11100001, 0b10101100, 0b00110011,
|
0b11111111, 0b11100001, 0b10101100, 0b00110011,
|
||||||
0b10100101, 0b11100000, 0b00000111, 0b00000001,
|
0b10100101, 0b11100000, 0b00000111, 0b00000001,
|
||||||
0b11001010, 0b10101111, 0b00101011, 0b01101010,
|
0b11001010, 0b10101111, 0b00101011, 0b01101010,
|
||||||
0b11010101, 0b10100011, 0b01010101, 0b11000001];
|
0b11010101, 0b10100011, 0b01010101, 0b11000001];
|
||||||
|
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 3).unwrap();
|
let n = read_bits_b(INPUT, p, 3).unwrap();
|
||||||
assert_eq!(n, 0b101);
|
assert_eq!(n, 0b101);
|
||||||
p += 3;
|
p += 3;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 63).unwrap();
|
let n = read_bits_b(INPUT, p, 63).unwrap();
|
||||||
assert_eq!(n, 0b001100101010100001000000000001111111110000111001101011100110010);
|
assert_eq!(n, 0b001100101010100001000000000001111111110000111001101011100110010);
|
||||||
p += 63;
|
p += 63;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 4).unwrap();
|
let n = read_bits_b(INPUT, p, 4).unwrap();
|
||||||
assert_eq!(n, 0b1001);
|
assert_eq!(n, 0b1001);
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 7).unwrap();
|
let n = read_bits_b(INPUT, p, 7).unwrap();
|
||||||
assert_eq!(n, 0b0100000);
|
assert_eq!(n, 0b0100000);
|
||||||
p += 7;
|
p += 7;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 17).unwrap();
|
let n = read_bits_b(INPUT, p, 17).unwrap();
|
||||||
assert_eq!(n, 0b11111100000100000);
|
assert_eq!(n, 0b11111100000100000);
|
||||||
p += 17;
|
p += 17;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 27).unwrap();
|
let n = read_bits_b(INPUT, p, 27).unwrap();
|
||||||
assert_eq!(n, 0b000101001111110101110101000);
|
assert_eq!(n, 0b000101001111110101110101000);
|
||||||
p += 27;
|
p += 27;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 33).unwrap();
|
let n = read_bits_b(INPUT, p, 33).unwrap();
|
||||||
assert_eq!(n, 0b101011010101011110001011010101010);
|
assert_eq!(n, 0b101011010101011110001011010101010);
|
||||||
p += 33;
|
p += 33;
|
||||||
|
|
||||||
let n = read_bits_b(INPUT, p, 6).unwrap();
|
let n = read_bits_b(INPUT, p, 6).unwrap();
|
||||||
assert_eq!(n, 0b000011);
|
assert_eq!(n, 0b000011);
|
||||||
p += 6;
|
p += 6;
|
||||||
|
|
||||||
let e = read_bits_b(INPUT, p, 1);
|
let e = read_bits_b(INPUT, p, 1);
|
||||||
assert!(if let Err(_) = e {true} else {false});
|
assert!(if let Err(_) = e {true} else {false});
|
||||||
|
|
||||||
let e = read_bits_b(INPUT, p, 2);
|
let e = read_bits_b(INPUT, p, 2);
|
||||||
assert!(if let Err(_) = e {true} else {false});
|
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();
|
let n = read_bits_l(INPUT, 0, 3).unwrap();
|
||||||
assert_eq!(n, 0b101);
|
assert_eq!(n, 0b101);
|
||||||
p += 3;
|
p += 3;
|
||||||
|
|
||||||
let n = read_bits_l(INPUT, p, 63).unwrap();
|
let n = read_bits_l(INPUT, p, 63).unwrap();
|
||||||
assert_eq!(n, 0b010011001110101100111000011111111100000000000100001010101001100);
|
assert_eq!(n, 0b010011001110101100111000011111111100000000000100001010101001100);
|
||||||
p += 63;
|
p += 63;
|
||||||
|
|
||||||
let n = read_bits_l(INPUT, p, 4).unwrap();
|
let n = read_bits_l(INPUT, p, 4).unwrap();
|
||||||
assert_eq!(n, 0b1001);
|
assert_eq!(n, 0b1001);
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
let n = read_bits_l(INPUT, p, 7).unwrap();
|
let n = read_bits_l(INPUT, p, 7).unwrap();
|
||||||
assert_eq!(n, 0b0000010);
|
assert_eq!(n, 0b0000010);
|
||||||
p += 7;
|
p += 7;
|
||||||
|
|
||||||
let n = read_bits_l(INPUT, p, 17).unwrap();
|
let n = read_bits_l(INPUT, p, 17).unwrap();
|
||||||
assert_eq!(n, 0b00000100000111111);
|
assert_eq!(n, 0b00000100000111111);
|
||||||
p += 17;
|
p += 17;
|
||||||
|
|
||||||
let n = read_bits_l(INPUT, p, 27).unwrap();
|
let n = read_bits_l(INPUT, p, 27).unwrap();
|
||||||
assert_eq!(n, 0b000101011101011111100101000);
|
assert_eq!(n, 0b000101011101011111100101000);
|
||||||
p += 27;
|
p += 27;
|
||||||
|
|
||||||
let n = read_bits_l(INPUT, p, 33).unwrap();
|
let n = read_bits_l(INPUT, p, 33).unwrap();
|
||||||
assert_eq!(n, 0b010101010110100011110101010110101);
|
assert_eq!(n, 0b010101010110100011110101010110101);
|
||||||
p += 33;
|
p += 33;
|
||||||
|
|
||||||
let n = read_bits_l(INPUT, p, 6).unwrap();
|
let n = read_bits_l(INPUT, p, 6).unwrap();
|
||||||
assert_eq!(n, 0b110000);
|
assert_eq!(n, 0b110000);
|
||||||
p += 6;
|
p += 6;
|
||||||
|
|
||||||
let e = read_bits_l(INPUT, p, 1);
|
let e = read_bits_l(INPUT, p, 1);
|
||||||
assert!(if let Err(_) = e {true} else {false});
|
assert!(if let Err(_) = e {true} else {false});
|
||||||
|
|
||||||
let e = read_bits_l(INPUT, p, 2);
|
let e = read_bits_l(INPUT, p, 2);
|
||||||
assert!(if let Err(_) = e {true} else {false});
|
assert!(if let Err(_) = e {true} else {false});
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -4,85 +4,85 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! c_bitfield
|
macro_rules! c_bitfield
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
$(#[$outer:meta])*
|
$(#[$outer:meta])*
|
||||||
pub struct $t:ident: $ti:ty {
|
pub struct $t:ident: $ti:ty {
|
||||||
$(
|
$(
|
||||||
$(#[$inner:ident $($args:tt)*])*
|
$(#[$inner:ident $($args:tt)*])*
|
||||||
$f:ident = $v:expr
|
$f:ident = $v:expr
|
||||||
),+
|
),+
|
||||||
$(,)?
|
$(,)?
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
bitflags! {
|
bitflags! {
|
||||||
$(#[$outer])*
|
$(#[$outer])*
|
||||||
pub struct $t: $ti {
|
pub struct $t: $ti {
|
||||||
$(
|
$(
|
||||||
$(#[$inner $($args)*])*
|
$(#[$inner $($args)*])*
|
||||||
const $f = 1 << $v;
|
const $f = 1 << $v;
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
impl std::str::FromStr for $t
|
impl std::str::FromStr for $t
|
||||||
{
|
{
|
||||||
type Err = $crate::err::ParseFlagError;
|
type Err = $crate::err::ParseFlagError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err>
|
fn from_str(s: &str) -> Result<Self, Self::Err>
|
||||||
{
|
{
|
||||||
let mut flags = Self::empty();
|
let mut flags = Self::empty();
|
||||||
|
|
||||||
for s in s.split('|') {
|
for s in s.split('|') {
|
||||||
match s {
|
match s {
|
||||||
$(
|
$(
|
||||||
stringify!($f) => flags.insert(Self::$f),
|
stringify!($f) => flags.insert(Self::$f),
|
||||||
)+
|
)+
|
||||||
"(none)" => (),
|
"(none)" => (),
|
||||||
_ => return Err(Self::Err::new(stringify!($t)))
|
_ => return Err(Self::Err::new(stringify!($t)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(flags)
|
Ok(flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test
|
mod test
|
||||||
{
|
{
|
||||||
use crate::err::ParseFlagError;
|
use crate::err::ParseFlagError;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
pub struct TestFlag: u16 {
|
pub struct TestFlag: u16 {
|
||||||
ZERO = 0,
|
ZERO = 0,
|
||||||
ONE = 1,
|
ONE = 1,
|
||||||
TWO = 2,
|
TWO = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn c_bitfield()
|
fn c_bitfield()
|
||||||
{
|
{
|
||||||
assert_eq!(TestFlag::from_bits(0), Some(TestFlag::empty()));
|
assert_eq!(TestFlag::from_bits(0), Some(TestFlag::empty()));
|
||||||
assert_eq!(TestFlag::from_bits(1), Some(TestFlag::ZERO));
|
assert_eq!(TestFlag::from_bits(1), Some(TestFlag::ZERO));
|
||||||
assert_eq!(TestFlag::from_bits(2), Some(TestFlag::ONE));
|
assert_eq!(TestFlag::from_bits(2), Some(TestFlag::ONE));
|
||||||
assert_eq!(TestFlag::from_bits(4), Some(TestFlag::TWO));
|
assert_eq!(TestFlag::from_bits(4), Some(TestFlag::TWO));
|
||||||
assert_eq!(TestFlag::from_bits(8), None);
|
assert_eq!(TestFlag::from_bits(8), None);
|
||||||
assert_eq!(TestFlag::from_str("(none)"), Ok(TestFlag::empty()));
|
assert_eq!(TestFlag::from_str("(none)"), Ok(TestFlag::empty()));
|
||||||
assert_eq!(TestFlag::from_str("ZERO"), Ok(TestFlag::ZERO));
|
assert_eq!(TestFlag::from_str("ZERO"), Ok(TestFlag::ZERO));
|
||||||
assert_eq!(TestFlag::from_str("ONE"), Ok(TestFlag::ONE));
|
assert_eq!(TestFlag::from_str("ONE"), Ok(TestFlag::ONE));
|
||||||
assert_eq!(TestFlag::from_str("TWO"), Ok(TestFlag::TWO));
|
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("ZERO|ONE|TWO"), Ok(TestFlag::all()));
|
||||||
assert_eq!(TestFlag::from_str("TWO|ZERO|ONE"), 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("ONE|ONE|ONE"), Ok(TestFlag::ONE));
|
||||||
assert_eq!(TestFlag::from_str("(none)|(none)"), Ok(TestFlag::empty()));
|
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("(none)|ONE"), Ok(TestFlag::ONE));
|
||||||
assert_eq!(TestFlag::from_str("THREE"),
|
assert_eq!(TestFlag::from_str("THREE"),
|
||||||
Err(ParseFlagError::new("TestFlag")));
|
Err(ParseFlagError::new("TestFlag")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
152
maraiah/cenum.rs
152
maraiah/cenum.rs
|
@ -16,11 +16,11 @@
|
||||||
/// use std::convert::TryFrom;
|
/// use std::convert::TryFrom;
|
||||||
///
|
///
|
||||||
/// c_enum! {
|
/// c_enum! {
|
||||||
/// enum MyEnum: u16 {
|
/// enum MyEnum: u16 {
|
||||||
/// Zero = 0,
|
/// Zero = 0,
|
||||||
/// One = 1,
|
/// One = 1,
|
||||||
/// Two = 2
|
/// Two = 2
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// assert_eq!(MyEnum::try_from(0), Ok(MyEnum::Zero));
|
/// assert_eq!(MyEnum::try_from(0), Ok(MyEnum::Zero));
|
||||||
|
@ -33,88 +33,88 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! c_enum
|
macro_rules! c_enum
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
$(#[$outer:meta])*
|
$(#[$outer:meta])*
|
||||||
$vi:vis enum $t:ident: $ti:ident {
|
$vi:vis enum $t:ident: $ti:ident {
|
||||||
$(
|
$(
|
||||||
$(#[$inner:meta])*
|
$(#[$inner:meta])*
|
||||||
$en:ident = $va:expr
|
$en:ident = $va:expr
|
||||||
),+
|
),+
|
||||||
$(,)?
|
$(,)?
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
$(#[$outer])*
|
$(#[$outer])*
|
||||||
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
#[repr($ti)]
|
#[repr($ti)]
|
||||||
$vi enum $t {
|
$vi enum $t {
|
||||||
$(
|
$(
|
||||||
$(#[$inner])*
|
$(#[$inner])*
|
||||||
$en = $va,
|
$en = $va,
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
impl std::convert::TryFrom<$ti> for $t
|
impl std::convert::TryFrom<$ti> for $t
|
||||||
{
|
{
|
||||||
type Error = $crate::err::ReprError;
|
type Error = $crate::err::ReprError;
|
||||||
|
|
||||||
/// Returns, if representable, the variant of `Self` from `n`.
|
/// Returns, if representable, the variant of `Self` from `n`.
|
||||||
fn try_from(n: $ti) -> Result<Self, Self::Error>
|
fn try_from(n: $ti) -> Result<Self, Self::Error>
|
||||||
{
|
{
|
||||||
match n {
|
match n {
|
||||||
$($va => Ok($t::$en),)+
|
$($va => Ok($t::$en),)+
|
||||||
n => Err(Self::Error::new(stringify!($t), n))
|
n => Err(Self::Error::new(stringify!($t), n))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
impl std::str::FromStr for $t
|
impl std::str::FromStr for $t
|
||||||
{
|
{
|
||||||
type Err = $crate::err::ParseEnumError;
|
type Err = $crate::err::ParseEnumError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err>
|
fn from_str(s: &str) -> Result<Self, Self::Err>
|
||||||
{
|
{
|
||||||
match s {
|
match s {
|
||||||
$(
|
$(
|
||||||
stringify!($en) => Ok($t::$en),
|
stringify!($en) => Ok($t::$en),
|
||||||
)+
|
)+
|
||||||
_ => Err(Self::Err::new(stringify!($t)))
|
_ => Err(Self::Err::new(stringify!($t)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test
|
mod test
|
||||||
{
|
{
|
||||||
use crate::err::{ParseEnumError, ReprError};
|
use crate::err::{ParseEnumError, ReprError};
|
||||||
use std::{convert::TryFrom, str::FromStr};
|
use std::{convert::TryFrom, str::FromStr};
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
enum TestEnum: u16 {
|
enum TestEnum: u16 {
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
One = 1,
|
One = 1,
|
||||||
Two = 2,
|
Two = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn c_enum()
|
fn c_enum()
|
||||||
{
|
{
|
||||||
assert_eq!(TestEnum::try_from(0), Ok(TestEnum::Zero));
|
assert_eq!(TestEnum::try_from(0), Ok(TestEnum::Zero));
|
||||||
assert_eq!(TestEnum::try_from(1), Ok(TestEnum::One));
|
assert_eq!(TestEnum::try_from(1), Ok(TestEnum::One));
|
||||||
assert_eq!(TestEnum::try_from(2), Ok(TestEnum::Two));
|
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(3), Err(ReprError::new("TestEnum", 3)));
|
||||||
assert_eq!(TestEnum::try_from(4), Err(ReprError::new("TestEnum", 4)));
|
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::try_from(5), Err(ReprError::new("TestEnum", 5)));
|
||||||
assert_eq!(TestEnum::from_str("Zero"), Ok(TestEnum::Zero));
|
assert_eq!(TestEnum::from_str("Zero"), Ok(TestEnum::Zero));
|
||||||
assert_eq!(TestEnum::from_str("One"), Ok(TestEnum::One));
|
assert_eq!(TestEnum::from_str("One"), Ok(TestEnum::One));
|
||||||
assert_eq!(TestEnum::from_str("Two"), Ok(TestEnum::Two));
|
assert_eq!(TestEnum::from_str("Two"), Ok(TestEnum::Two));
|
||||||
assert_eq!(TestEnum::from_str("Three"),
|
assert_eq!(TestEnum::from_str("Three"),
|
||||||
Err(ParseEnumError::new("TestEnum")));
|
Err(ParseEnumError::new("TestEnum")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -3,22 +3,22 @@
|
||||||
// Accumulator for CRC function.
|
// Accumulator for CRC function.
|
||||||
fn crc_accum(a: u32, _: u32) -> u32
|
fn crc_accum(a: u32, _: u32) -> u32
|
||||||
{
|
{
|
||||||
if a & 1 == 1 {
|
if a & 1 == 1 {
|
||||||
ISO_3309_POLYNOMIAL ^ a >> 1
|
ISO_3309_POLYNOMIAL ^ a >> 1
|
||||||
} else {
|
} else {
|
||||||
a >> 1
|
a >> 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes a CRC array.
|
// Initializes a CRC array.
|
||||||
// FIXME: use const fn when stabilized
|
// FIXME: use const fn when stabilized
|
||||||
fn crc_init() -> [u32; 256]
|
fn crc_init() -> [u32; 256]
|
||||||
{
|
{
|
||||||
let mut t = [0; 256];
|
let mut t = [0; 256];
|
||||||
for (n, v) in t.iter_mut().enumerate() {
|
for (n, v) in t.iter_mut().enumerate() {
|
||||||
*v = (0..8).fold(n as u32, crc_accum);
|
*v = (0..8).fold(n as u32, crc_accum);
|
||||||
}
|
}
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an ADLER32 of all bytes in `b`.
|
/// Creates an ADLER32 of all bytes in `b`.
|
||||||
|
@ -32,16 +32,16 @@ fn crc_init() -> [u32; 256]
|
||||||
/// ```
|
/// ```
|
||||||
pub fn adler32(b: &[u8]) -> u32
|
pub fn adler32(b: &[u8]) -> u32
|
||||||
{
|
{
|
||||||
let mut x = 1;
|
let mut x = 1;
|
||||||
let mut y = 0;
|
let mut y = 0;
|
||||||
|
|
||||||
for &z in b {
|
for &z in b {
|
||||||
let z = u32::from(z);
|
let z = u32::from(z);
|
||||||
x = (x + z) % ADLER32_MODULO;
|
x = (x + z) % ADLER32_MODULO;
|
||||||
y = (y + x) % 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
|
/// 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
|
pub fn crc32(b: &[u8], s: u32) -> u32
|
||||||
{
|
{
|
||||||
let t = crc_init();
|
let t = crc_init();
|
||||||
!b.iter().fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)])
|
!b.iter().fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)])
|
||||||
}
|
}
|
||||||
|
|
||||||
const ISO_3309_POLYNOMIAL: u32 = 0xEDB8_8320;
|
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.
|
/// Loads a ZLIB file header.
|
||||||
pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
|
pub fn load_zlib_header(b: &[u8]) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
const CM: u8 = 0b0000_1111;
|
const CM: u8 = 0b0000_1111;
|
||||||
const CINFO: u8 = 0b1111_0000;
|
const CINFO: u8 = 0b1111_0000;
|
||||||
const FDICT: u8 = 0b0010_0000;
|
const FDICT: u8 = 0b0010_0000;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 2, start: 0, data {
|
endian: BIG, buf: b, size: 2, start: 0, data {
|
||||||
let fcheck = u16[0];
|
let fcheck = u16[0];
|
||||||
let cmf = u8[0];
|
let cmf = u8[0];
|
||||||
let flg = u8[1];
|
let flg = u8[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cm = cmf & CM;
|
let cm = cmf & CM;
|
||||||
let cinfo = cmf & CINFO;
|
let cinfo = cmf & CINFO;
|
||||||
|
|
||||||
if cm != 8 {
|
if cm != 8 {
|
||||||
bail!("unknown compression method");
|
bail!("unknown compression method");
|
||||||
}
|
}
|
||||||
|
|
||||||
if cinfo > 7 << 4 {
|
if cinfo > 7 << 4 {
|
||||||
bail!("lz77 window size logarithm is invalid");
|
bail!("lz77 window size logarithm is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
if fcheck % 31 != 0 {
|
if fcheck % 31 != 0 {
|
||||||
bail!("invalid fcheck");
|
bail!("invalid fcheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
if flg & FDICT != 0 {
|
if flg & FDICT != 0 {
|
||||||
bail!("dictionary not supported");
|
bail!("dictionary not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(2)
|
Ok(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a GZIP file header.
|
/// Loads a GZIP file header.
|
||||||
pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
const FHCRC: u8 = 1 << 1;
|
const FHCRC: u8 = 1 << 1;
|
||||||
const FEXTRA: u8 = 1 << 2;
|
const FEXTRA: u8 = 1 << 2;
|
||||||
const FNAME: u8 = 1 << 3;
|
const FNAME: u8 = 1 << 3;
|
||||||
const FCOMMENT: u8 = 1 << 4;
|
const FCOMMENT: u8 = 1 << 4;
|
||||||
const FRESERVED: u8 = 0xe0;
|
const FRESERVED: u8 = 0xe0;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: LITTLE, buf: b, size: 10, start: 0, data {
|
endian: LITTLE, buf: b, size: 10, start: 0, data {
|
||||||
let id = u16[0];
|
let id = u16[0];
|
||||||
let cm = u8[2];
|
let cm = u8[2];
|
||||||
let fl = u8[3];
|
let fl = u8[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if id != 0x8b1f || cm != 8 {
|
if id != 0x8b1f || cm != 8 {
|
||||||
bail!("not gzip format");
|
bail!("not gzip format");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut p = 10;
|
let mut p = 10;
|
||||||
|
|
||||||
if fl & FRESERVED != 0 {
|
if fl & FRESERVED != 0 {
|
||||||
bail!("reserved flags set");
|
bail!("reserved flags set");
|
||||||
}
|
}
|
||||||
|
|
||||||
if fl & FEXTRA != 0 {
|
if fl & FEXTRA != 0 {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: LITTLE, buf: b, size: 2, start: p, data {
|
endian: LITTLE, buf: b, size: 2, start: p, data {
|
||||||
let xlen = u16[0] usize;
|
let xlen = u16[0] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p += 2 + xlen;
|
p += 2 + xlen;
|
||||||
|
|
||||||
check_data(b, p)?;
|
check_data(b, p)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fl & FNAME != 0 {
|
if fl & FNAME != 0 {
|
||||||
p += skip_zero_terminated_item(&b[p..])?;
|
p += skip_zero_terminated_item(&b[p..])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fl & FCOMMENT != 0 {
|
if fl & FCOMMENT != 0 {
|
||||||
p += skip_zero_terminated_item(&b[p..])?;
|
p += skip_zero_terminated_item(&b[p..])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fl & FHCRC != 0 {
|
if fl & FHCRC != 0 {
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
check_data(b, p)?;
|
check_data(b, p)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(p)
|
Ok(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip_zero_terminated_item(b: &[u8]) -> ResultS<usize>
|
fn skip_zero_terminated_item(b: &[u8]) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
if let Some(i) = b.iter().position(|&n| n == 0) {
|
if let Some(i) = b.iter().position(|&n| n == 0) {
|
||||||
Ok(i + 1)
|
Ok(i + 1)
|
||||||
} else {
|
} else {
|
||||||
bail!("no end of zero terminated item");
|
bail!("no end of zero terminated item");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decompresses a DEFLATE compressed bitstream.
|
/// Decompresses a DEFLATE compressed bitstream.
|
||||||
pub fn load_deflate(b: &[u8]) -> ResultS<(usize, Vec<u8>)>
|
pub fn load_deflate(b: &[u8]) -> ResultS<(usize, Vec<u8>)>
|
||||||
{
|
{
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let bfinal = read_bits_l(b, p, 1)?;
|
let bfinal = read_bits_l(b, p, 1)?;
|
||||||
p += 1;
|
p += 1;
|
||||||
let btype = read_bits_l(b, p, 2)?;
|
let btype = read_bits_l(b, p, 2)?;
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
match btype {
|
match btype {
|
||||||
0b10 => p = stream_dynamic(&mut v, b, p)?,
|
0b10 => p = stream_dynamic(&mut v, b, p)?,
|
||||||
0b01 => p = stream_s_table(&mut v, b, p)?,
|
0b01 => p = stream_s_table(&mut v, b, p)?,
|
||||||
0b00 => p = stream_literal(&mut v, b, p)?,
|
0b00 => p = stream_literal(&mut v, b, p)?,
|
||||||
_ => bail!("bad btype"),
|
_ => bail!("bad btype"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if bfinal == 1 {
|
if bfinal == 1 {
|
||||||
return Ok((p / 8, v));
|
return Ok((p / 8, v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_dynamic(v: &mut Vec<u8>, b: &[u8], mut p: usize) -> ResultS<usize>
|
fn stream_dynamic(v: &mut Vec<u8>, b: &[u8], mut p: usize) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
const CODE_ORDERING: [usize; 19] =
|
const CODE_ORDERING: [usize; 19] =
|
||||||
[16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
|
[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
|
// read header (number of literal alphabet codes, number of distance
|
||||||
// alphabet codes, and number of lengths for decoding the alphabet)
|
// alphabet codes, and number of lengths for decoding the alphabet)
|
||||||
let hlit = read_bits_l(b, p, 5)?;
|
let hlit = read_bits_l(b, p, 5)?;
|
||||||
p += 5;
|
p += 5;
|
||||||
let hdist = read_bits_l(b, p, 5)?;
|
let hdist = read_bits_l(b, p, 5)?;
|
||||||
p += 5;
|
p += 5;
|
||||||
let hclen = read_bits_l(b, p, 4)?;
|
let hclen = read_bits_l(b, p, 4)?;
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
let hlit = 257 + hlit as usize;
|
let hlit = 257 + hlit as usize;
|
||||||
let hdist = 1 + hdist as usize;
|
let hdist = 1 + hdist as usize;
|
||||||
let hclen = 4 + hclen as usize;
|
let hclen = 4 + hclen as usize;
|
||||||
|
|
||||||
// first, get the huffman coding for the alphabet (which is also compressed)
|
// first, get the huffman coding for the alphabet (which is also compressed)
|
||||||
let mut code_table = [0; 19];
|
let mut code_table = [0; 19];
|
||||||
|
|
||||||
for i in 0..hclen {
|
for i in 0..hclen {
|
||||||
let len = read_bits_l(b, p, 3)? as u16;
|
let len = read_bits_l(b, p, 3)? as u16;
|
||||||
p += 3;
|
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
|
// then, we decode the alphabet (doing both types at the same time, because
|
||||||
// they're encoded the same anyways)
|
// they're encoded the same anyways)
|
||||||
let code_table = HuffmanTable::new(&code_table)?;
|
let code_table = HuffmanTable::new(&code_table)?;
|
||||||
let mut alphabet = vec![0; hlit + hdist];
|
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 {
|
if alphabet[256] == 0 {
|
||||||
bail!("no way to end block");
|
bail!("no way to end block");
|
||||||
}
|
}
|
||||||
|
|
||||||
// build the length and distance tables from this information
|
// build the length and distance tables from this information
|
||||||
let table_len = HuffmanTable::new(&alphabet[0..hlit])?;
|
let table_len = HuffmanTable::new(&alphabet[0..hlit])?;
|
||||||
let table_dst = HuffmanTable::new(&alphabet[hlit..hlit + hdist])?;
|
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)]
|
#[allow(clippy::needless_range_loop)]
|
||||||
fn stream_s_table(v: &mut Vec<u8>, b: &[u8], p: usize) -> ResultS<usize>
|
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 0..144 {len[i] = 8;}
|
||||||
for i in 144..256 {len[i] = 9;}
|
for i in 144..256 {len[i] = 9;}
|
||||||
for i in 256..280 {len[i] = 7;}
|
for i in 256..280 {len[i] = 7;}
|
||||||
for i in 280..288 {len[i] = 8;}
|
for i in 280..288 {len[i] = 8;}
|
||||||
|
|
||||||
let dst = [5; 30];
|
let dst = [5; 30];
|
||||||
|
|
||||||
let table_len = HuffmanTable::new(&len)?;
|
let table_len = HuffmanTable::new(&len)?;
|
||||||
let table_dst = HuffmanTable::new(&dst)?;
|
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>
|
fn stream_literal(v: &mut Vec<u8>, b: &[u8], p: usize) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
// copy data directly from byte boundary
|
// copy data directly from byte boundary
|
||||||
let mut p = p / 8 + 1;
|
let mut p = p / 8 + 1;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: LITTLE, buf: b, size: 4, start: p, data {
|
endian: LITTLE, buf: b, size: 4, start: p, data {
|
||||||
let len = u16[0] usize;
|
let len = u16[0] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p += 4;
|
p += 4;
|
||||||
v.extend(ok!(b.get(p..p + len), "not enough data")?);
|
v.extend(ok!(b.get(p..p + len), "not enough data")?);
|
||||||
|
|
||||||
Ok((p + len) * 8)
|
Ok((p + len) * 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_alphabet(b: &[u8],
|
fn read_alphabet(b: &[u8],
|
||||||
|
@ -216,63 +216,63 @@ fn read_alphabet(b: &[u8],
|
||||||
alphabet: &mut [u16],
|
alphabet: &mut [u16],
|
||||||
code_table: HuffmanTable) -> ResultS<usize>
|
code_table: HuffmanTable) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < alphabet.len() {
|
while i < alphabet.len() {
|
||||||
let (bits, sym) = code_table.decode(b, p)?;
|
let (bits, sym) = code_table.decode(b, p)?;
|
||||||
p += bits;
|
p += bits;
|
||||||
|
|
||||||
match sym {
|
match sym {
|
||||||
0..=15 => {
|
0..=15 => {
|
||||||
// raw code
|
// raw code
|
||||||
alphabet[i] = sym;
|
alphabet[i] = sym;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
16 => {
|
16 => {
|
||||||
// copy previous code 3-6 times
|
// copy previous code 3-6 times
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
bail!("cannot copy on first alphabet code");
|
bail!("cannot copy on first alphabet code");
|
||||||
}
|
}
|
||||||
|
|
||||||
let len = usize::from(read_bits_l(b, p, 2)? as u8 + 3);
|
let len = usize::from(read_bits_l(b, p, 2)? as u8 + 3);
|
||||||
let lst = alphabet[i - 1];
|
let lst = alphabet[i - 1];
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
alphabet[i] = lst;
|
alphabet[i] = lst;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
17 => {
|
17 => {
|
||||||
// repeat '0' 3-10 times
|
// repeat '0' 3-10 times
|
||||||
let len = usize::from(read_bits_l(b, p, 3)? as u8 + 3);
|
let len = usize::from(read_bits_l(b, p, 3)? as u8 + 3);
|
||||||
p += 3;
|
p += 3;
|
||||||
|
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
alphabet[i] = 0;
|
alphabet[i] = 0;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
18 => {
|
18 => {
|
||||||
// repeat '0' 11-138 times
|
// repeat '0' 11-138 times
|
||||||
let len = usize::from(read_bits_l(b, p, 7)? as u8 + 11);
|
let len = usize::from(read_bits_l(b, p, 7)? as u8 + 11);
|
||||||
p += 7;
|
p += 7;
|
||||||
|
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
alphabet[i] = 0;
|
alphabet[i] = 0;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bail!("bad symbol in alphabet");
|
bail!("bad symbol in alphabet");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i > alphabet.len() {
|
if i > alphabet.len() {
|
||||||
bail!("too many codes");
|
bail!("too many codes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(p)
|
Ok(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_tables(v: &mut Vec<u8>,
|
fn output_tables(v: &mut Vec<u8>,
|
||||||
|
@ -281,145 +281,145 @@ fn output_tables(v: &mut Vec<u8>,
|
||||||
table_len: HuffmanTable,
|
table_len: HuffmanTable,
|
||||||
table_dst: HuffmanTable) -> ResultS<usize>
|
table_dst: HuffmanTable) -> ResultS<usize>
|
||||||
{
|
{
|
||||||
const LEN_BASE: [usize; 29] = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19,
|
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,
|
23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115,
|
||||||
131, 163, 195, 227, 258];
|
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,
|
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,
|
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
|
||||||
0];
|
0];
|
||||||
|
|
||||||
const DST_BASE: [usize; 30] = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65,
|
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,
|
97, 129, 193, 257, 385, 513, 769, 1025,
|
||||||
1537, 2049, 3073, 4097, 0x1801, 0x2001,
|
1537, 2049, 3073, 4097, 0x1801, 0x2001,
|
||||||
0x3001, 0x4001, 0x6001];
|
0x3001, 0x4001, 0x6001];
|
||||||
|
|
||||||
const DST_EXTRA_BITS: [u8; 30] = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
|
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,
|
6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
||||||
12, 12, 13, 13];
|
12, 12, 13, 13];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (bits, sym) = table_len.decode(b, p)?;
|
let (bits, sym) = table_len.decode(b, p)?;
|
||||||
p += bits;
|
p += bits;
|
||||||
|
|
||||||
match sym.cmp(&256) {
|
match sym.cmp(&256) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
// direct byte
|
// direct byte
|
||||||
v.push(sym as u8);
|
v.push(sym as u8);
|
||||||
}
|
}
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
return Ok(p);
|
return Ok(p);
|
||||||
}
|
}
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
// this is a <len, dst> pair
|
// this is a <len, dst> pair
|
||||||
let sym = sym - 257;
|
let sym = sym - 257;
|
||||||
|
|
||||||
if sym > 29 {
|
if sym > 29 {
|
||||||
bail!("invalid fixed code");
|
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
|
// first get the actual length and any extra bits it may have
|
||||||
let bits = LEN_EXTRA_BITS[sym];
|
let bits = LEN_EXTRA_BITS[sym];
|
||||||
let leng = LEN_BASE[sym] + read_bits_l(b, p, bits)? as usize;
|
let leng = LEN_BASE[sym] + read_bits_l(b, p, bits)? as usize;
|
||||||
p += usize::from(bits);
|
p += usize::from(bits);
|
||||||
|
|
||||||
// decode the distance with its alphabet
|
// decode the distance with its alphabet
|
||||||
let (bits, sym) = table_dst.decode(b, p)?;
|
let (bits, sym) = table_dst.decode(b, p)?;
|
||||||
p += bits;
|
p += bits;
|
||||||
|
|
||||||
let sym = usize::from(sym);
|
let sym = usize::from(sym);
|
||||||
|
|
||||||
// get the actual distance and any extra bits it may have
|
// get the actual distance and any extra bits it may have
|
||||||
let bits = DST_EXTRA_BITS[sym];
|
let bits = DST_EXTRA_BITS[sym];
|
||||||
let dist = DST_BASE[sym] + read_bits_l(b, p, bits)? as usize;
|
let dist = DST_BASE[sym] + read_bits_l(b, p, bits)? as usize;
|
||||||
p += usize::from(bits);
|
p += usize::from(bits);
|
||||||
|
|
||||||
if dist > v.len() {
|
if dist > v.len() {
|
||||||
bail!("bad distance");
|
bail!("bad distance");
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy bytes from earlier
|
// copy bytes from earlier
|
||||||
for _ in 0..leng {
|
for _ in 0..leng {
|
||||||
v.push(v[v.len() - dist]);
|
v.push(v[v.len() - dist]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HuffmanTable
|
impl HuffmanTable
|
||||||
{
|
{
|
||||||
fn new(table: &[u16]) -> ResultS<Self>
|
fn new(table: &[u16]) -> ResultS<Self>
|
||||||
{
|
{
|
||||||
let mut syms = vec![0; table.len()];
|
let mut syms = vec![0; table.len()];
|
||||||
let mut nums = [0; 16];
|
let mut nums = [0; 16];
|
||||||
|
|
||||||
// count the number of symbols for each bit length
|
// count the number of symbols for each bit length
|
||||||
for &length in table {
|
for &length in table {
|
||||||
nums[usize::from(length)] += 1;
|
nums[usize::from(length)] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if usize::from(nums[0]) == table.len() {
|
if usize::from(nums[0]) == table.len() {
|
||||||
bail!("bad table lengths");
|
bail!("bad table lengths");
|
||||||
}
|
}
|
||||||
|
|
||||||
// make offsets into the symbol table for each bit count
|
// make offsets into the symbol table for each bit count
|
||||||
let mut ofs = [0; 16];
|
let mut ofs = [0; 16];
|
||||||
|
|
||||||
for i in 1..=14 {
|
for i in 1..=14 {
|
||||||
ofs[i + 1] = ofs[i] + usize::from(nums[i]);
|
ofs[i + 1] = ofs[i] + usize::from(nums[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make the actual bit pattern table
|
// make the actual bit pattern table
|
||||||
for (n, &length) in table.iter().enumerate() {
|
for (n, &length) in table.iter().enumerate() {
|
||||||
// length 0 means this code isn't used, so only try to make bit
|
// length 0 means this code isn't used, so only try to make bit
|
||||||
// patterns for codes that actually exist
|
// patterns for codes that actually exist
|
||||||
if length != 0 {
|
if length != 0 {
|
||||||
// make sure to make each offset unique
|
// make sure to make each offset unique
|
||||||
let offset = &mut ofs[usize::from(length)];
|
let offset = &mut ofs[usize::from(length)];
|
||||||
syms[*offset] = n as u16;
|
syms[*offset] = n as u16;
|
||||||
*offset += 1;
|
*offset += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self{nums, syms})
|
Ok(Self{nums, syms})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode(&self, b: &[u8], mut p: usize) -> ResultS<(usize, u16)>
|
fn decode(&self, b: &[u8], mut p: usize) -> ResultS<(usize, u16)>
|
||||||
{
|
{
|
||||||
let mut code = 0_u16;
|
let mut code = 0_u16;
|
||||||
let mut first = 0_u16;
|
let mut first = 0_u16;
|
||||||
let mut index = 0_u16;
|
let mut index = 0_u16;
|
||||||
|
|
||||||
for i in 1..=15 {
|
for i in 1..=15 {
|
||||||
// add bit from file
|
// add bit from file
|
||||||
code |= read_bits_l(b, p, 1)? as u16;
|
code |= read_bits_l(b, p, 1)? as u16;
|
||||||
p += 1;
|
p += 1;
|
||||||
|
|
||||||
// check our symbol table for this one (quick tree check)
|
// check our symbol table for this one (quick tree check)
|
||||||
let count = self.nums[i];
|
let count = self.nums[i];
|
||||||
|
|
||||||
if i32::from(code) - i32::from(count) < i32::from(first) {
|
if i32::from(code) - i32::from(count) < i32::from(first) {
|
||||||
return Ok((i, self.syms[usize::from(index + code - first)]));
|
return Ok((i, self.syms[usize::from(index + code - first)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// continue on, trying to find the correct sequence
|
// continue on, trying to find the correct sequence
|
||||||
index += count;
|
index += count;
|
||||||
first += count;
|
first += count;
|
||||||
|
|
||||||
first <<= 1;
|
first <<= 1;
|
||||||
code <<= 1;
|
code <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ReprError::new("DEFLATE code", code).into())
|
Err(ReprError::new("DEFLATE code", code).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HuffmanTable {
|
struct HuffmanTable {
|
||||||
nums: [u16; 16],
|
nums: [u16; 16],
|
||||||
syms: Vec<u16>,
|
syms: Vec<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -8,15 +8,15 @@
|
||||||
/// use maraiah::doc_comment;
|
/// use maraiah::doc_comment;
|
||||||
///
|
///
|
||||||
/// doc_comment! {
|
/// doc_comment! {
|
||||||
/// concat!("Have a nice", " day", "!"),
|
/// concat!("Have a nice", " day", "!"),
|
||||||
/// const A: u32 = 5;
|
/// const A: u32 = 5;
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// assert_eq!(A, 5);
|
/// assert_eq!(A, 5);
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! doc_comment {
|
macro_rules! doc_comment {
|
||||||
($x:expr, $($tt:tt)*) => {#[doc = $x] $($tt)*}
|
($x:expr, $($tt:tt)*) => {#[doc = $x] $($tt)*}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
166
maraiah/err.rs
166
maraiah/err.rs
|
@ -5,40 +5,40 @@ pub use failure::{Error, Fail};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
macro_rules! ok {
|
macro_rules! ok {
|
||||||
($v:expr, $msg:expr) => {
|
($v:expr, $msg:expr) => {
|
||||||
match $v {
|
match $v {
|
||||||
Some(v) => Ok(v),
|
Some(v) => Ok(v),
|
||||||
None => Err($crate::err::err_msg($msg)),
|
None => Err($crate::err::err_msg($msg)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! flag_ok {
|
macro_rules! flag_ok {
|
||||||
($t:ident$(::$tc:ident)*, $v:expr) => {
|
($t:ident$(::$tc:ident)*, $v:expr) => {
|
||||||
{
|
{
|
||||||
let v = $v;
|
let v = $v;
|
||||||
|
|
||||||
match $t$(::$tc)*::from_bits(v) {
|
match $t$(::$tc)*::from_bits(v) {
|
||||||
Some(v) => Ok(v),
|
Some(v) => Ok(v),
|
||||||
None => Err($crate::err::ReprError::new(stringify!($t), v)),
|
None => Err($crate::err::ReprError::new(stringify!($t), v)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! bail {
|
macro_rules! bail {
|
||||||
($e:expr) => {
|
($e:expr) => {
|
||||||
return Err($crate::err::err_msg($e));
|
return Err($crate::err::err_msg($e));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! backtrace {
|
macro_rules! backtrace {
|
||||||
($e:expr) => {
|
($e:expr) => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
dbg!($e.backtrace());
|
dbg!($e.backtrace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an `Error` with a static string.
|
/// Returns an `Error` with a static string.
|
||||||
|
@ -55,58 +55,58 @@ pub fn err_msg(msg: &'static str) -> Error {ErrMsg(msg).into()}
|
||||||
|
|
||||||
impl ParseEnumError
|
impl ParseEnumError
|
||||||
{
|
{
|
||||||
/// Returns an `Error` with a message for enumeration parsing errata.
|
/// Returns an `Error` with a message for enumeration parsing errata.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use maraiah::err::ParseEnumError;
|
/// use maraiah::err::ParseEnumError;
|
||||||
///
|
///
|
||||||
/// assert_eq!(format!("{}", ParseEnumError::new("TypeName")),
|
/// assert_eq!(format!("{}", ParseEnumError::new("TypeName")),
|
||||||
/// "could not parse TypeName");
|
/// "could not parse TypeName");
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(t: &'static str) -> Self
|
pub const fn new(t: &'static str) -> Self
|
||||||
{
|
{
|
||||||
Self(t)
|
Self(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseFlagError
|
impl ParseFlagError
|
||||||
{
|
{
|
||||||
/// Returns an `Error` with a message for flag parsing errata.
|
/// Returns an `Error` with a message for flag parsing errata.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use maraiah::err::ParseFlagError;
|
/// use maraiah::err::ParseFlagError;
|
||||||
///
|
///
|
||||||
/// assert_eq!(format!("{}", ParseFlagError::new("TypeName")),
|
/// assert_eq!(format!("{}", ParseFlagError::new("TypeName")),
|
||||||
/// "could not parse TypeName");
|
/// "could not parse TypeName");
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(t: &'static str) -> Self
|
pub const fn new(t: &'static str) -> Self
|
||||||
{
|
{
|
||||||
Self(t)
|
Self(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReprError
|
impl ReprError
|
||||||
{
|
{
|
||||||
/// Returns an `Error` with a message for representation errata.
|
/// Returns an `Error` with a message for representation errata.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use maraiah::err::ReprError;
|
/// use maraiah::err::ReprError;
|
||||||
///
|
///
|
||||||
/// assert_eq!(format!("{}", ReprError::new("TypeName", 77)),
|
/// assert_eq!(format!("{}", ReprError::new("TypeName", 77)),
|
||||||
/// "bad TypeName (77)");
|
/// "bad TypeName (77)");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new<T: Into<i64>>(t: &'static str, n: T) -> Self
|
pub fn new<T: Into<i64>>(t: &'static str, n: T) -> Self
|
||||||
{
|
{
|
||||||
Self(t, n.into())
|
Self(t, n.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fail for ErrMsg {}
|
impl Fail for ErrMsg {}
|
||||||
|
@ -116,34 +116,34 @@ impl Fail for ReprError {}
|
||||||
|
|
||||||
impl fmt::Display for ParseEnumError
|
impl fmt::Display for ParseEnumError
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
{
|
{
|
||||||
write!(f, "could not parse {}", self.0)
|
write!(f, "could not parse {}", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ParseFlagError
|
impl fmt::Display for ParseFlagError
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
{
|
{
|
||||||
write!(f, "could not parse {}", self.0)
|
write!(f, "could not parse {}", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ReprError
|
impl fmt::Display for ReprError
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
{
|
{
|
||||||
write!(f, "bad {} ({})", self.0, self.1)
|
write!(f, "bad {} ({})", self.0, self.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ErrMsg
|
impl fmt::Display for ErrMsg
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
{
|
{
|
||||||
f.write_str(self.0)
|
f.write_str(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -19,14 +19,14 @@ pub use std::{ffi::*, os::raw::*, ptr::{null, null_mut}};
|
||||||
/// assert!(!st.is_null());
|
/// assert!(!st.is_null());
|
||||||
///
|
///
|
||||||
/// unsafe {
|
/// 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_export]
|
||||||
macro_rules! c_str {
|
macro_rules! c_str {
|
||||||
($s:expr) => {
|
($s:expr) => {
|
||||||
concat!($s, "\0").as_ptr() as $crate::ffi::NT
|
concat!($s, "\0").as_ptr() as $crate::ffi::NT
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns [`null`] as a [`*const c_void`].
|
/// Returns [`null`] as a [`*const c_void`].
|
||||||
|
@ -45,49 +45,49 @@ pub const fn null_mut_void() -> *mut c_void {null_mut()}
|
||||||
|
|
||||||
impl CStringVec
|
impl CStringVec
|
||||||
{
|
{
|
||||||
/// Creates a new `CStringVec` from an iterator.
|
/// Creates a new `CStringVec` from an iterator.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_from_iter<'a, I>(it: I) -> ResultS<Self>
|
pub fn new_from_iter<'a, I>(it: I) -> ResultS<Self>
|
||||||
where I: Iterator<Item = &'a str>
|
where I: Iterator<Item = &'a str>
|
||||||
{
|
{
|
||||||
let mut v = Self::default();
|
let mut v = Self::default();
|
||||||
|
|
||||||
for st in it {
|
for st in it {
|
||||||
v.push(CString::new(st)?);
|
v.push(CString::new(st)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a new `CString`.
|
/// Pushes a new `CString`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn push(&mut self, st: CString)
|
pub fn push(&mut self, st: CString)
|
||||||
{
|
{
|
||||||
self.cv.insert(self.cv.len() - 1, st.as_ptr());
|
self.cv.insert(self.cv.len() - 1, st.as_ptr());
|
||||||
self.sv.push(st);
|
self.sv.push(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the FFI pointer.
|
/// Returns the FFI pointer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_ptr(&self) -> *const NT {self.cv.as_ptr()}
|
pub fn as_ptr(&self) -> *const NT {self.cv.as_ptr()}
|
||||||
|
|
||||||
/// Returns the FFI pointer mutably.
|
/// Returns the FFI pointer mutably.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut NT {self.cv.as_mut_ptr()}
|
pub fn as_mut_ptr(&mut self) -> *mut NT {self.cv.as_mut_ptr()}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CStringVec
|
impl Default for CStringVec
|
||||||
{
|
{
|
||||||
/// Creates a new empty CStringVec.
|
/// Creates a new empty CStringVec.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {Self{sv: Vec::new(), cv: vec![null()]}}
|
fn default() -> Self {Self{sv: Vec::new(), cv: vec![null()]}}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An owned null-terminated string vector.
|
/// An owned null-terminated string vector.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CStringVec {
|
pub struct CStringVec {
|
||||||
sv: Vec<CString>,
|
sv: Vec<CString>,
|
||||||
cv: Vec<NT>,
|
cv: Vec<NT>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A null-terminated byte string pointer.
|
/// 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.
|
/// Confirms that the path `p` is a folder.
|
||||||
pub fn validate_folder_path(p: &str) -> ResultS<()>
|
pub fn validate_folder_path(p: &str) -> ResultS<()>
|
||||||
{
|
{
|
||||||
let at = fs::metadata(p)?;
|
let at = fs::metadata(p)?;
|
||||||
if at.is_dir() {
|
if at.is_dir() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(err_msg("not a directory"))
|
Err(err_msg("not a directory"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens the file at `path` and skips past any macintosh headers.
|
/// Opens the file at `path` and skips past any macintosh headers.
|
||||||
pub fn open_mac<P: AsRef<Path>>(path: P) -> ResultS<fs::File>
|
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>
|
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>
|
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>
|
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>
|
impl<T> SeekBackToStart<T>
|
||||||
where T: Seek
|
where T: Seek
|
||||||
{
|
{
|
||||||
/// Creates a new `SeekBackToStart` object.
|
/// Creates a new `SeekBackToStart` object.
|
||||||
pub fn new(sc: T) -> Self {Self{sc, fl: true}}
|
pub fn new(sc: T) -> Self {Self{sc, fl: true}}
|
||||||
|
|
||||||
/// Sets the seek-back flag.
|
/// Sets the seek-back flag.
|
||||||
pub fn set_seek(&mut self, fl: bool) {self.fl = fl;}
|
pub fn set_seek(&mut self, fl: bool) {self.fl = fl;}
|
||||||
|
|
||||||
/// Returns the seek-back flag.
|
/// Returns the seek-back flag.
|
||||||
pub fn get_seek(&self) -> bool {self.fl}
|
pub fn get_seek(&self) -> bool {self.fl}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Seeks back to the starting position of the inner object when losing scope,
|
/// Seeks back to the starting position of the inner object when losing scope,
|
||||||
/// unless a flag is set.
|
/// unless a flag is set.
|
||||||
pub struct SeekBackToStart<T: Seek> {
|
pub struct SeekBackToStart<T: Seek> {
|
||||||
sc: T,
|
sc: T,
|
||||||
fl: bool,
|
fl: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// 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]
|
#[inline]
|
||||||
pub const fn r5g5b5_to_rgb8(rgb: u16) -> Color8
|
pub const fn r5g5b5_to_rgb8(rgb: u16) -> Color8
|
||||||
{
|
{
|
||||||
let r = (rgb >> 10) as u8 & 0x1f;
|
let r = (rgb >> 10) as u8 & 0x1f;
|
||||||
let g = (rgb >> 5) as u8 & 0x1f;
|
let g = (rgb >> 5) as u8 & 0x1f;
|
||||||
let b = rgb as u8 & 0x1f;
|
let b = rgb as u8 & 0x1f;
|
||||||
Color8::new(r << 3, g << 3, b << 3)
|
Color8::new(r << 3, g << 3, b << 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a RGB16 color from a R5G5B5 format color.
|
/// Creates a RGB16 color from a R5G5B5 format color.
|
||||||
|
@ -35,10 +35,10 @@ pub const fn r5g5b5_to_rgb8(rgb: u16) -> Color8
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn r5g5b5_to_rgb16(rgb: u16) -> Color16
|
pub const fn r5g5b5_to_rgb16(rgb: u16) -> Color16
|
||||||
{
|
{
|
||||||
let r = rgb >> 10 & 0x1f;
|
let r = rgb >> 10 & 0x1f;
|
||||||
let g = rgb >> 5 & 0x1f;
|
let g = rgb >> 5 & 0x1f;
|
||||||
let b = rgb & 0x1f;
|
let b = rgb & 0x1f;
|
||||||
Color16::new(r << 11, g << 11, b << 11)
|
Color16::new(r << 11, g << 11, b << 11)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a RGB16 color from a RGB8 format color.
|
/// 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
|
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.
|
/// A generic color matrix image.
|
||||||
pub trait Image
|
pub trait Image
|
||||||
{
|
{
|
||||||
/// The type of color this image uses for each pixel.
|
/// The type of color this image uses for each pixel.
|
||||||
type Output: Color;
|
type Output: Color;
|
||||||
|
|
||||||
/// Returns the width of the image.
|
/// Returns the width of the image.
|
||||||
fn w(&self) -> usize;
|
fn w(&self) -> usize;
|
||||||
|
|
||||||
/// Returns the height of the image.
|
/// Returns the height of the image.
|
||||||
fn h(&self) -> usize;
|
fn h(&self) -> usize;
|
||||||
|
|
||||||
/// Returns the color of the pixel at column `x` at row `y`.
|
/// Returns the color of the pixel at column `x` at row `y`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `x` is greater than the width of the image or `y` is greater
|
/// Panics if `x` is greater than the width of the image or `y` is greater
|
||||||
/// than the height of the image.
|
/// than the height of the image.
|
||||||
fn index(&self, x: usize, y: usize) -> &Self::Output;
|
fn index(&self, x: usize, y: usize) -> &Self::Output;
|
||||||
|
|
||||||
/// The same as `index`, but will not panic if out of bounds.
|
/// The same as `index`, but will not panic if out of bounds.
|
||||||
fn get(&self, x: usize, y: usize) -> Option<&Self::Output>
|
fn get(&self, x: usize, y: usize) -> Option<&Self::Output>
|
||||||
{
|
{
|
||||||
if x < self.w() && y < self.h() {
|
if x < self.w() && y < self.h() {
|
||||||
Some(self.index(x, y))
|
Some(self.index(x, y))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A generic color matrix image, which may be mutated.
|
/// A generic color matrix image, which may be mutated.
|
||||||
pub trait ImageMut: Image
|
pub trait ImageMut: Image
|
||||||
{
|
{
|
||||||
/// Returns the color of the pixel at column `x` at row `y`.
|
/// Returns the color of the pixel at column `x` at row `y`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `x` is greater than the width of the image or `y` is greater
|
/// Panics if `x` is greater than the width of the image or `y` is greater
|
||||||
/// than the height of the image.
|
/// than the height of the image.
|
||||||
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output;
|
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.
|
/// 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>
|
fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut Self::Output>
|
||||||
{
|
{
|
||||||
if x < self.w() && y < self.h() {
|
if x < self.w() && y < self.h() {
|
||||||
Some(self.index_mut(x, y))
|
Some(self.index_mut(x, y))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Any color which may be represented as RGBA16.
|
/// Any color which may be represented as RGBA16.
|
||||||
pub trait Color: Sized + Copy + Clone + Eq + PartialEq
|
pub trait Color: Sized + Copy + Clone + Eq + PartialEq
|
||||||
{
|
{
|
||||||
/// Returns the red component.
|
/// Returns the red component.
|
||||||
fn r(&self) -> u16;
|
fn r(&self) -> u16;
|
||||||
|
|
||||||
/// Returns the green component.
|
/// Returns the green component.
|
||||||
fn g(&self) -> u16;
|
fn g(&self) -> u16;
|
||||||
|
|
||||||
/// Returns the blue component.
|
/// Returns the blue component.
|
||||||
fn b(&self) -> u16;
|
fn b(&self) -> u16;
|
||||||
|
|
||||||
/// Returns the alpha component.
|
/// Returns the alpha component.
|
||||||
fn a(&self) -> u16;
|
fn a(&self) -> u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image16
|
impl Image16
|
||||||
{
|
{
|
||||||
/// Creates a new Image16 with no canvas.
|
/// Creates a new Image16 with no canvas.
|
||||||
pub fn new(w: usize, h: usize) -> Self
|
pub fn new(w: usize, h: usize) -> Self
|
||||||
{
|
{
|
||||||
Self{w, h, cr: Vec::with_capacity(w * h)}
|
Self{w, h, cr: Vec::with_capacity(w * h)}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new Image16 with an empty canvas.
|
/// Creates a new Image16 with an empty canvas.
|
||||||
pub fn new_empty(w: usize, h: usize) -> Self
|
pub fn new_empty(w: usize, h: usize) -> Self
|
||||||
{
|
{
|
||||||
Self{w, h, cr: vec![Color16::new(0, 0, 0); w * h]}
|
Self{w, h, cr: vec![Color16::new(0, 0, 0); w * h]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image for Image16
|
impl Image for Image16
|
||||||
{
|
{
|
||||||
type Output = Color16;
|
type Output = Color16;
|
||||||
|
|
||||||
fn w(&self) -> usize {self.w}
|
fn w(&self) -> usize {self.w}
|
||||||
fn h(&self) -> usize {self.h}
|
fn h(&self) -> usize {self.h}
|
||||||
|
|
||||||
fn index(&self, x: usize, y: usize) -> &Self::Output
|
fn index(&self, x: usize, y: usize) -> &Self::Output
|
||||||
{
|
{
|
||||||
&self.cr[x + y * self.w]
|
&self.cr[x + y * self.w]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageMut for Image16
|
impl ImageMut for Image16
|
||||||
{
|
{
|
||||||
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
|
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
|
||||||
{
|
{
|
||||||
&mut self.cr[x + y * self.w]
|
&mut self.cr[x + y * self.w]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image8
|
impl Image8
|
||||||
{
|
{
|
||||||
/// Creates a new Image8 with no canvas.
|
/// Creates a new Image8 with no canvas.
|
||||||
pub fn new(w: usize, h: usize) -> Self
|
pub fn new(w: usize, h: usize) -> Self
|
||||||
{
|
{
|
||||||
Self{w, h, cr: Vec::with_capacity(w * h)}
|
Self{w, h, cr: Vec::with_capacity(w * h)}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new Image8 with an empty canvas.
|
/// Creates a new Image8 with an empty canvas.
|
||||||
pub fn new_empty(w: usize, h: usize) -> Self
|
pub fn new_empty(w: usize, h: usize) -> Self
|
||||||
{
|
{
|
||||||
Self{w, h, cr: vec![Color8::new(0, 0, 0); w * h]}
|
Self{w, h, cr: vec![Color8::new(0, 0, 0); w * h]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image for Image8
|
impl Image for Image8
|
||||||
{
|
{
|
||||||
type Output = Color8;
|
type Output = Color8;
|
||||||
|
|
||||||
fn w(&self) -> usize {self.w}
|
fn w(&self) -> usize {self.w}
|
||||||
fn h(&self) -> usize {self.h}
|
fn h(&self) -> usize {self.h}
|
||||||
|
|
||||||
fn index(&self, x: usize, y: usize) -> &Self::Output
|
fn index(&self, x: usize, y: usize) -> &Self::Output
|
||||||
{
|
{
|
||||||
&self.cr[x + y * self.w]
|
&self.cr[x + y * self.w]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageMut for Image8
|
impl ImageMut for Image8
|
||||||
{
|
{
|
||||||
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
|
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
|
||||||
{
|
{
|
||||||
&mut self.cr[x + y * self.w]
|
&mut self.cr[x + y * self.w]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Color16
|
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
|
impl Color for Color16
|
||||||
{
|
{
|
||||||
fn r(&self) -> u16 {self.0}
|
fn r(&self) -> u16 {self.0}
|
||||||
fn g(&self) -> u16 {self.1}
|
fn g(&self) -> u16 {self.1}
|
||||||
fn b(&self) -> u16 {self.2}
|
fn b(&self) -> u16 {self.2}
|
||||||
fn a(&self) -> u16 {u16::max_value()}
|
fn a(&self) -> u16 {u16::max_value()}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Color8
|
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
|
impl Color for Color8
|
||||||
{
|
{
|
||||||
fn r(&self) -> u16 {u16::from(self.0) << 8}
|
fn r(&self) -> u16 {u16::from(self.0) << 8}
|
||||||
fn g(&self) -> u16 {u16::from(self.1) << 8}
|
fn g(&self) -> u16 {u16::from(self.1) << 8}
|
||||||
fn b(&self) -> u16 {u16::from(self.2) << 8}
|
fn b(&self) -> u16 {u16::from(self.2) << 8}
|
||||||
fn a(&self) -> u16 {u16::max_value()}
|
fn a(&self) -> u16 {u16::max_value()}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An RGB16 color.
|
/// An RGB16 color.
|
||||||
|
@ -239,22 +239,22 @@ pub struct Color8(u8, u8, u8);
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Image16 {
|
pub struct Image16 {
|
||||||
w: usize,
|
w: usize,
|
||||||
h: usize,
|
h: usize,
|
||||||
|
|
||||||
/// The raw color data for this image.
|
/// The raw color data for this image.
|
||||||
pub cr: Vec<Color16>,
|
pub cr: Vec<Color16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An RGB8 image.
|
/// An RGB8 image.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Image8 {
|
pub struct Image8 {
|
||||||
w: usize,
|
w: usize,
|
||||||
h: usize,
|
h: usize,
|
||||||
|
|
||||||
/// The raw color data for this image.
|
/// The raw color data for this image.
|
||||||
pub cr: Vec<Color8>,
|
pub cr: Vec<Color8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -9,109 +9,109 @@ use crate::{bin::*, err::*, image::*};
|
||||||
/// Load a `PICT` image.
|
/// Load a `PICT` image.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Image8>
|
pub fn read(b: &[u8]) -> ResultS<Image8>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 10, start: 0, data {
|
endian: BIG, buf: b, size: 10, start: 0, data {
|
||||||
let h = u16[6] usize;
|
let h = u16[6] usize;
|
||||||
let w = u16[8] usize;
|
let w = u16[8] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if w * h > 16_000_000 {
|
if w * h > 16_000_000 {
|
||||||
bail!("image is too large");
|
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() {
|
while p < b.len() {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 2, start: p, data {
|
endian: BIG, buf: b, size: 2, start: p, data {
|
||||||
let op = u16[0];
|
let op = u16[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
0x0098 => {
|
0x0098 => {
|
||||||
// PackBitsRect
|
// PackBitsRect
|
||||||
return pm::area::read(im, &b[p..], true, false);
|
return pm::area::read(im, &b[p..], true, false);
|
||||||
}
|
}
|
||||||
0x0099 => {
|
0x0099 => {
|
||||||
// PackBitsRgn
|
// PackBitsRgn
|
||||||
return pm::area::read(im, &b[p..], true, true);
|
return pm::area::read(im, &b[p..], true, true);
|
||||||
}
|
}
|
||||||
0x009a => {
|
0x009a => {
|
||||||
// DirectBitsRect
|
// DirectBitsRect
|
||||||
return pm::area::read(im, &b[p..], false, false);
|
return pm::area::read(im, &b[p..], false, false);
|
||||||
}
|
}
|
||||||
0x009b => {
|
0x009b => {
|
||||||
// DirectBitsRgn
|
// DirectBitsRgn
|
||||||
return pm::area::read(im, &b[p..], false, true);
|
return pm::area::read(im, &b[p..], false, true);
|
||||||
}
|
}
|
||||||
0x8200 => {
|
0x8200 => {
|
||||||
// CompressedQuickTime
|
// CompressedQuickTime
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
0x00ff => {
|
0x00ff => {
|
||||||
// OpEndPic
|
// OpEndPic
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// help i'm trapped in an awful metafile format from the 80s
|
// help i'm trapped in an awful metafile format from the 80s
|
||||||
0x0000 | // NoOp
|
0x0000 | // NoOp
|
||||||
0x001c | // HiliteMode
|
0x001c | // HiliteMode
|
||||||
0x001e | // DefHilite
|
0x001e | // DefHilite
|
||||||
0x0038 | // FrameSameRect
|
0x0038 | // FrameSameRect
|
||||||
0x0039 | // PaintSameRect
|
0x0039 | // PaintSameRect
|
||||||
0x003a | // EraseSameRect
|
0x003a | // EraseSameRect
|
||||||
0x003b | // InvertSameRect
|
0x003b | // InvertSameRect
|
||||||
0x003c | // FillSameRect
|
0x003c | // FillSameRect
|
||||||
0x8000 | // Reserved
|
0x8000 | // Reserved
|
||||||
0x8100 => (), // Reserved
|
0x8100 => (), // Reserved
|
||||||
0x0003 | // TxFont
|
0x0003 | // TxFont
|
||||||
0x0004 | // TxFace
|
0x0004 | // TxFace
|
||||||
0x0005 | // TxMode
|
0x0005 | // TxMode
|
||||||
0x0008 | // PnMode
|
0x0008 | // PnMode
|
||||||
0x000d | // TxSize
|
0x000d | // TxSize
|
||||||
0x0011 | // VersionOp
|
0x0011 | // VersionOp
|
||||||
0x0015 | // PnLocHFrac
|
0x0015 | // PnLocHFrac
|
||||||
0x0016 | // ChExtra
|
0x0016 | // ChExtra
|
||||||
0x0023 | // ShortLineFrom
|
0x0023 | // ShortLineFrom
|
||||||
0x00a0 => p += 2, // ShortComment
|
0x00a0 => p += 2, // ShortComment
|
||||||
0x0006 | // SpExtra
|
0x0006 | // SpExtra
|
||||||
0x0007 | // PnSize
|
0x0007 | // PnSize
|
||||||
0x000b | // OvSize
|
0x000b | // OvSize
|
||||||
0x000c | // Origin
|
0x000c | // Origin
|
||||||
0x000e | // FgCol
|
0x000e | // FgCol
|
||||||
0x000f | // BkCol
|
0x000f | // BkCol
|
||||||
0x0021 => p += 4, // LineFrom
|
0x0021 => p += 4, // LineFrom
|
||||||
0x001a | // RGBFgCol
|
0x001a | // RGBFgCol
|
||||||
0x001b | // RGBBkCol
|
0x001b | // RGBBkCol
|
||||||
0x001d | // TxRatio
|
0x001d | // TxRatio
|
||||||
0x0022 => p += 6, // ShortLine
|
0x0022 => p += 6, // ShortLine
|
||||||
0x0002 | // BkPat
|
0x0002 | // BkPat
|
||||||
0x0009 | // PnPat
|
0x0009 | // PnPat
|
||||||
0x0010 | // TxRatio
|
0x0010 | // TxRatio
|
||||||
0x0020 | // Line
|
0x0020 | // Line
|
||||||
0x002e | // GlyphState
|
0x002e | // GlyphState
|
||||||
0x0030 | // FrameRect
|
0x0030 | // FrameRect
|
||||||
0x0031 | // PaintRect
|
0x0031 | // PaintRect
|
||||||
0x0032 | // EraseRect
|
0x0032 | // EraseRect
|
||||||
0x0033 | // InvertRect
|
0x0033 | // InvertRect
|
||||||
0x0034 => p += 8, // FillRect
|
0x0034 => p += 8, // FillRect
|
||||||
0x002d => p += 10, // LineJustify
|
0x002d => p += 10, // LineJustify
|
||||||
0x0001 => p += usize::from(u16b(&b[p.. ]) & !1), // Clip
|
0x0001 => p += usize::from(u16b(&b[p.. ]) & !1), // Clip
|
||||||
0x00a1 => p += usize::from(u16b(&b[p+2..]) & !1) + 2, // LongComment
|
0x00a1 => p += usize::from(u16b(&b[p+2..]) & !1) + 2, // LongComment
|
||||||
0x100..=
|
0x100..=
|
||||||
0x7fff => p += usize::from(op >> 8) * 2, // Reserved
|
0x7fff => p += usize::from(op >> 8) * 2, // Reserved
|
||||||
_ => {
|
_ => {
|
||||||
bail!("invalid op in PICT");
|
bail!("invalid op in PICT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(err_msg("no image in data"))
|
Err(err_msg("no image in data"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,38 +5,38 @@ use crate::{err::*, image::*};
|
||||||
/// Read a `ColorTable` structure.
|
/// Read a `ColorTable` structure.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 8, start: 0, data {
|
endian: BIG, buf: b, size: 8, start: 0, data {
|
||||||
let dev = u16[4];
|
let dev = u16[4];
|
||||||
let num = u16[6] usize;
|
let num = u16[6] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dev = dev & 0x8000 != 0;
|
let dev = dev & 0x8000 != 0;
|
||||||
let num = num + 1;
|
let num = num + 1;
|
||||||
|
|
||||||
let mut p = 8;
|
let mut p = 8;
|
||||||
let mut clut = vec![Color8::new(0, 0, 0); num];
|
let mut clut = vec![Color8::new(0, 0, 0); num];
|
||||||
|
|
||||||
for i in 0..num {
|
for i in 0..num {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 8, start: p, data {
|
endian: BIG, buf: b, size: 8, start: p, data {
|
||||||
let n = u16[0] usize;
|
let n = u16[0] usize;
|
||||||
let r = u8[2];
|
let r = u8[2];
|
||||||
let g = u8[4];
|
let g = u8[4];
|
||||||
let b = u8[6];
|
let b = u8[6];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// with device mapping, we ignore the index entirely
|
// with device mapping, we ignore the index entirely
|
||||||
let n = if dev {i} else {n};
|
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
|
// EOF
|
||||||
|
|
|
@ -5,17 +5,17 @@ use crate::{err::*, image::{*, pict::pm}};
|
||||||
/// Process a `CopyBits` operation.
|
/// Process a `CopyBits` operation.
|
||||||
pub fn read(im: Image8, b: &[u8], pack: bool, clip: bool) -> ResultS<Image8>
|
pub fn read(im: Image8, b: &[u8], pack: bool, clip: bool) -> ResultS<Image8>
|
||||||
{
|
{
|
||||||
let p = if pack {0} else {4};
|
let p = if pack {0} else {4};
|
||||||
let (b, hdr) = pm::head::read(&b[p..], pack, clip, &im)?;
|
let (b, hdr) = pm::head::read(&b[p..], pack, clip, &im)?;
|
||||||
|
|
||||||
match hdr.depth {
|
match hdr.depth {
|
||||||
pm::head::Depth::_1 |
|
pm::head::Depth::_1 |
|
||||||
pm::head::Depth::_2 |
|
pm::head::Depth::_2 |
|
||||||
pm::head::Depth::_4 |
|
pm::head::Depth::_4 |
|
||||||
pm::head::Depth::_8 => pm::ind::read(im, b, hdr),
|
pm::head::Depth::_8 => pm::ind::read(im, b, hdr),
|
||||||
pm::head::Depth::_16 => pm::r5g5b5::read(im, b, hdr),
|
pm::head::Depth::_16 => pm::r5g5b5::read(im, b, hdr),
|
||||||
pm::head::Depth::_32 => pm::rgb8::read(im, b, hdr),
|
pm::head::Depth::_32 => pm::rgb8::read(im, b, hdr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -8,79 +8,79 @@ pub fn read<'a>(b: &'a [u8],
|
||||||
clip: bool,
|
clip: bool,
|
||||||
im: &Image8) -> ResultS<(&'a [u8], Header)>
|
im: &Image8) -> ResultS<(&'a [u8], Header)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 36, start: 0, data {
|
endian: BIG, buf: b, size: 36, start: 0, data {
|
||||||
let pt_fl = u16[0];
|
let pt_fl = u16[0];
|
||||||
let top = u16[2] usize;
|
let top = u16[2] usize;
|
||||||
let left = u16[4] usize;
|
let left = u16[4] usize;
|
||||||
let bottom = u16[6] usize;
|
let bottom = u16[6] usize;
|
||||||
let right = u16[8] usize;
|
let right = u16[8] usize;
|
||||||
let pack_t = u16[12] enum PackType;
|
let pack_t = u16[12] enum PackType;
|
||||||
let depth = u16[28] enum Depth;
|
let depth = u16[28] enum Depth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if pt_fl & 0x8000 == 0 {
|
if pt_fl & 0x8000 == 0 {
|
||||||
bail!("PICT1 not supported");
|
bail!("PICT1 not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
if right - left != im.w() || bottom - top != im.h() {
|
if right - left != im.w() || bottom - top != im.h() {
|
||||||
bail!("image bounds are incorrect");
|
bail!("image bounds are incorrect");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut p = 46;
|
let mut p = 46;
|
||||||
|
|
||||||
// get CLUT if packed
|
// get CLUT if packed
|
||||||
let clut = if pack {
|
let clut = if pack {
|
||||||
let (clut, sz) = pict::clut::read(&b[p..])?;
|
let (clut, sz) = pict::clut::read(&b[p..])?;
|
||||||
p += sz;
|
p += sz;
|
||||||
Some(clut)
|
Some(clut)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
p += 18; // srcRect, dstRect, mode
|
p += 18; // srcRect, dstRect, mode
|
||||||
|
|
||||||
if clip {
|
if clip {
|
||||||
p += usize::from(u16b(&b[p..])); // maskRgn
|
p += usize::from(u16b(&b[p..])); // maskRgn
|
||||||
}
|
}
|
||||||
|
|
||||||
let rle = pack_t == PackType::Default ||
|
let rle = pack_t == PackType::Default ||
|
||||||
pack_t == PackType::Rle16 && depth == Depth::_16 ||
|
pack_t == PackType::Rle16 && depth == Depth::_16 ||
|
||||||
pack_t == PackType::Rle32 && depth == Depth::_32;
|
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 struct Header {
|
||||||
pub pitch: usize,
|
pub pitch: usize,
|
||||||
pub pack_t: PackType,
|
pub pack_t: PackType,
|
||||||
pub depth: Depth,
|
pub depth: Depth,
|
||||||
pub clut: Option<Vec<Color8>>,
|
pub clut: Option<Vec<Color8>>,
|
||||||
pub rle: bool,
|
pub rle: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
pub enum Depth: u16 {
|
pub enum Depth: u16 {
|
||||||
_1 = 1,
|
_1 = 1,
|
||||||
_2 = 2,
|
_2 = 2,
|
||||||
_4 = 4,
|
_4 = 4,
|
||||||
_8 = 8,
|
_8 = 8,
|
||||||
_16 = 16,
|
_16 = 16,
|
||||||
_32 = 32,
|
_32 = 32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
pub enum PackType: u16 {
|
pub enum PackType: u16 {
|
||||||
Default = 0,
|
Default = 0,
|
||||||
None = 1,
|
None = 1,
|
||||||
NoPad = 2,
|
NoPad = 2,
|
||||||
Rle16 = 3,
|
Rle16 = 3,
|
||||||
Rle32 = 4,
|
Rle32 = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,81 +7,80 @@ pub fn read(mut im: Image8,
|
||||||
b: &[u8],
|
b: &[u8],
|
||||||
hdr: pm::head::Header) -> ResultS<Image8>
|
hdr: pm::head::Header) -> ResultS<Image8>
|
||||||
{
|
{
|
||||||
let clut = ok!(hdr.clut, "no CLUT in indexed mode")?;
|
let clut = ok!(hdr.clut, "no CLUT in indexed mode")?;
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
if hdr.pitch < 8 && hdr.depth == pm::head::Depth::_8 {
|
if hdr.pitch < 8 && hdr.depth == pm::head::Depth::_8 {
|
||||||
// uncompressed 8-bit colormap indices
|
// uncompressed 8-bit colormap indices
|
||||||
for _ in 0..im.h() {
|
for _ in 0..im.h() {
|
||||||
for _ in 0..im.w() {
|
for _ in 0..im.w() {
|
||||||
let idx = usize::from(b[p]);
|
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)
|
Ok(im)
|
||||||
} else if hdr.rle {
|
} else if hdr.rle {
|
||||||
// RLE compressed 1, 2, 4 or 8 bit colormap indices
|
// RLE compressed 1, 2, 4 or 8 bit colormap indices
|
||||||
for _ in 0..im.h() {
|
for _ in 0..im.h() {
|
||||||
let (d, pp) = rle::read::<u8>(&b[p..], hdr.pitch)?;
|
let (d, pp) = rle::read::<u8>(&b[p..], hdr.pitch)?;
|
||||||
|
|
||||||
let d = if hdr.depth < pm::head::Depth::_8 {
|
let d = if hdr.depth < pm::head::Depth::_8 {
|
||||||
expand_data(d, hdr.depth)?
|
expand_data(d, hdr.depth)?
|
||||||
} else {
|
} else {
|
||||||
d
|
d
|
||||||
};
|
};
|
||||||
|
|
||||||
check_data(&d, im.w())?;
|
check_data(&d, im.w())?;
|
||||||
|
|
||||||
p += pp;
|
p += pp;
|
||||||
|
|
||||||
for &idx in &d {
|
for &idx in &d {
|
||||||
im.cr
|
im.cr.push(ok!(clut.get(usize::from(idx)), "bad index")?.clone());
|
||||||
.push(ok!(clut.get(usize::from(idx)), "invalid index")?.clone());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(im)
|
Ok(im)
|
||||||
} else {
|
} else {
|
||||||
bail!("invalid configuration")
|
bail!("invalid configuration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand packed pixel data based on bit depth.
|
/// Expand packed pixel data based on bit depth.
|
||||||
pub fn expand_data(b: Vec<u8>, depth: pm::head::Depth) -> ResultS<Vec<u8>>
|
pub fn expand_data(b: Vec<u8>, depth: pm::head::Depth) -> ResultS<Vec<u8>>
|
||||||
{
|
{
|
||||||
let mut o = Vec::with_capacity(match depth {
|
let mut o = Vec::with_capacity(match depth {
|
||||||
pm::head::Depth::_4 => b.len() * 2,
|
pm::head::Depth::_4 => b.len() * 2,
|
||||||
pm::head::Depth::_2 => b.len() * 4,
|
pm::head::Depth::_2 => b.len() * 4,
|
||||||
pm::head::Depth::_1 => b.len() * 8,
|
pm::head::Depth::_1 => b.len() * 8,
|
||||||
_ => bail!("invalid bit depth"),
|
_ => bail!("invalid bit depth"),
|
||||||
});
|
});
|
||||||
|
|
||||||
for ch in b {
|
for ch in b {
|
||||||
match depth {
|
match depth {
|
||||||
pm::head::Depth::_4 => {
|
pm::head::Depth::_4 => {
|
||||||
for i in (0..=1).rev() {
|
for i in (0..=1).rev() {
|
||||||
o.push(ch >> (i * 4) & 0xF_u8);
|
o.push(ch >> (i * 4) & 0xF_u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pm::head::Depth::_2 => {
|
pm::head::Depth::_2 => {
|
||||||
for i in (0..=3).rev() {
|
for i in (0..=3).rev() {
|
||||||
o.push(ch >> (i * 2) & 0x3_u8);
|
o.push(ch >> (i * 2) & 0x3_u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pm::head::Depth::_1 => {
|
pm::head::Depth::_1 => {
|
||||||
for i in (0..=7).rev() {
|
for i in (0..=7).rev() {
|
||||||
o.push(ch >> i & 0x1_u8);
|
o.push(ch >> i & 0x1_u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bail!("invalid bit depth"),
|
_ => bail!("invalid bit depth"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(o)
|
Ok(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,38 +7,38 @@ pub fn read(mut im: Image8,
|
||||||
b: &[u8],
|
b: &[u8],
|
||||||
hdr: pm::head::Header) -> ResultS<Image8>
|
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 {
|
if hdr.pitch < 8 || hdr.pack_t == pm::head::PackType::None {
|
||||||
// uncompressed R5G5B5
|
// uncompressed R5G5B5
|
||||||
for _ in 0..im.h() {
|
for _ in 0..im.h() {
|
||||||
for _ in 0..im.w() {
|
for _ in 0..im.w() {
|
||||||
let cr = u16b(&b[p..]);
|
let cr = u16b(&b[p..]);
|
||||||
|
|
||||||
im.cr.push(r5g5b5_to_rgb8(cr));
|
im.cr.push(r5g5b5_to_rgb8(cr));
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(im)
|
Ok(im)
|
||||||
} else if hdr.rle {
|
} else if hdr.rle {
|
||||||
// RLE compressed R5G5B5
|
// RLE compressed R5G5B5
|
||||||
for _ in 0..im.h() {
|
for _ in 0..im.h() {
|
||||||
let (d, pp) = rle::read::<u16>(&b[p..], hdr.pitch)?;
|
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 {
|
for &cr in &d {
|
||||||
im.cr.push(r5g5b5_to_rgb8(cr));
|
im.cr.push(r5g5b5_to_rgb8(cr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(im)
|
Ok(im)
|
||||||
} else {
|
} else {
|
||||||
bail!("invalid configuration")
|
bail!("invalid configuration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,56 +7,56 @@ pub fn read(mut im: Image8,
|
||||||
b: &[u8],
|
b: &[u8],
|
||||||
hdr: pm::head::Header) -> ResultS<Image8>
|
hdr: pm::head::Header) -> ResultS<Image8>
|
||||||
{
|
{
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
if hdr.pitch < 8 ||
|
if hdr.pitch < 8 ||
|
||||||
hdr.pack_t == pm::head::PackType::None ||
|
hdr.pack_t == pm::head::PackType::None ||
|
||||||
hdr.pack_t == pm::head::PackType::NoPad
|
hdr.pack_t == pm::head::PackType::NoPad
|
||||||
{
|
{
|
||||||
// uncompressed RGB8 or XRGB8
|
// uncompressed RGB8 or XRGB8
|
||||||
for _ in 0..im.h() {
|
for _ in 0..im.h() {
|
||||||
for _ in 0..im.w() {
|
for _ in 0..im.w() {
|
||||||
if hdr.pack_t != pm::head::PackType::NoPad {
|
if hdr.pack_t != pm::head::PackType::NoPad {
|
||||||
p += 1;
|
p += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 3, start: p, data {
|
endian: BIG, buf: b, size: 3, start: p, data {
|
||||||
let r = u8[0];
|
let r = u8[0];
|
||||||
let g = u8[1];
|
let g = u8[1];
|
||||||
let b = u8[2];
|
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)
|
Ok(im)
|
||||||
} else if hdr.rle {
|
} else if hdr.rle {
|
||||||
// RLE compressed RGB8
|
// RLE compressed RGB8
|
||||||
let pitch = hdr.pitch - im.w(); // remove padding byte from pitch
|
let pitch = hdr.pitch - im.w(); // remove padding byte from pitch
|
||||||
for _ in 0..im.h() {
|
for _ in 0..im.h() {
|
||||||
let (d, pp) = rle::read::<u8>(&b[p..], pitch)?;
|
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() {
|
for x in 0..im.w() {
|
||||||
let r = d[x];
|
let r = d[x];
|
||||||
let g = d[x * 2];
|
let g = d[x * 2];
|
||||||
let b = d[x * 3];
|
let b = d[x * 3];
|
||||||
im.cr.push(Color8::new(r, g, b));
|
im.cr.push(Color8::new(r, g, b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(im)
|
Ok(im)
|
||||||
} else {
|
} else {
|
||||||
bail!("invalid configuration")
|
bail!("invalid configuration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -4,91 +4,91 @@ use crate::{bin::*, err::*};
|
||||||
|
|
||||||
/// Read run-length encoded data.
|
/// Read run-length encoded data.
|
||||||
pub fn read<T>(b: &[u8], pitch: usize) -> ResultS<(Vec<T>, usize)>
|
pub fn read<T>(b: &[u8], pitch: usize) -> ResultS<(Vec<T>, usize)>
|
||||||
where T: ReadRleData
|
where T: ReadRleData
|
||||||
{
|
{
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
let mut o = Vec::with_capacity(pitch);
|
let mut o = Vec::with_capacity(pitch);
|
||||||
|
|
||||||
let sz = if pitch > 250 {
|
let sz = if pitch > 250 {
|
||||||
(usize::from(u16b(b)) + 2, p += 2).0
|
(usize::from(u16b(b)) + 2, p += 2).0
|
||||||
} else {
|
} else {
|
||||||
(usize::from(b[0]) + 1, p += 1).0
|
(usize::from(b[0]) + 1, p += 1).0
|
||||||
};
|
};
|
||||||
|
|
||||||
while p < sz {
|
while p < sz {
|
||||||
let szf = b[p];
|
let szf = b[p];
|
||||||
let cmp = szf & 0x80 != 0;
|
let cmp = szf & 0x80 != 0;
|
||||||
let len = usize::from(if cmp {!szf + 2} else {szf + 1});
|
let len = usize::from(if cmp {!szf + 2} else {szf + 1});
|
||||||
|
|
||||||
p += 1;
|
p += 1;
|
||||||
o.reserve(len);
|
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 {
|
if o.len() == pitch {
|
||||||
Ok((o, p))
|
Ok((o, p))
|
||||||
} else {
|
} else {
|
||||||
Err(err_msg("incorrect size for compressed scanline"))
|
Err(err_msg("incorrect size for compressed scanline"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ReadRleData: Sized
|
pub trait ReadRleData: Sized
|
||||||
{
|
{
|
||||||
// Read a sequence of packed RLE data.
|
// Read a sequence of packed RLE data.
|
||||||
fn read_rle_data(b: &[u8],
|
fn read_rle_data(b: &[u8],
|
||||||
p: &mut usize,
|
p: &mut usize,
|
||||||
cmp: bool,
|
cmp: bool,
|
||||||
len: usize,
|
len: usize,
|
||||||
out: &mut Vec<Self>);
|
out: &mut Vec<Self>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRleData for u16
|
impl ReadRleData for u16
|
||||||
{
|
{
|
||||||
fn read_rle_data(b: &[u8],
|
fn read_rle_data(b: &[u8],
|
||||||
p: &mut usize,
|
p: &mut usize,
|
||||||
cmp: bool,
|
cmp: bool,
|
||||||
len: usize,
|
len: usize,
|
||||||
out: &mut Vec<Self>)
|
out: &mut Vec<Self>)
|
||||||
{
|
{
|
||||||
if cmp {
|
if cmp {
|
||||||
let d = u16b(&b[*p..*p + 2]);
|
let d = u16b(&b[*p..*p + 2]);
|
||||||
*p += 2;
|
*p += 2;
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
out.push(d);
|
out.push(d);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
let d = u16b(&b[*p..*p + 2]);
|
let d = u16b(&b[*p..*p + 2]);
|
||||||
*p += 2;
|
*p += 2;
|
||||||
out.push(d);
|
out.push(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRleData for u8
|
impl ReadRleData for u8
|
||||||
{
|
{
|
||||||
fn read_rle_data(b: &[u8],
|
fn read_rle_data(b: &[u8],
|
||||||
p: &mut usize,
|
p: &mut usize,
|
||||||
cmp: bool,
|
cmp: bool,
|
||||||
len: usize,
|
len: usize,
|
||||||
out: &mut Vec<Self>)
|
out: &mut Vec<Self>)
|
||||||
{
|
{
|
||||||
if cmp {
|
if cmp {
|
||||||
let d = b[*p];
|
let d = b[*p];
|
||||||
*p += 1;
|
*p += 1;
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
out.push(d);
|
out.push(d);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
let d = b[*p];
|
let d = b[*p];
|
||||||
*p += 1;
|
*p += 1;
|
||||||
out.push(d);
|
out.push(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -10,60 +10,60 @@ use std::io;
|
||||||
/// Errors if `out` cannot be written to.
|
/// Errors if `out` cannot be written to.
|
||||||
pub fn write_ppm(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
|
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 y in 0..im.h() {
|
||||||
for x in 0..im.w() {
|
for x in 0..im.w() {
|
||||||
let cr = im.index(x, y);
|
let cr = im.index(x, y);
|
||||||
write!(out, "{} {} {} ", cr.r(), cr.g(), cr.b())?;
|
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.
|
/// Reads a PPM file into an image.
|
||||||
pub fn read_ppm(inp: &[u8]) -> ResultS<Image16>
|
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" {
|
if ok!(it.next(), "no magic number")? != b"P3" {
|
||||||
bail!("not P3 format");
|
bail!("not P3 format");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut get_num = move || -> ResultS<u16> {
|
let mut get_num = move || -> ResultS<u16> {
|
||||||
let st = loop {
|
let st = loop {
|
||||||
match ok!(it.next(), "no more strings")? {
|
match ok!(it.next(), "no more strings")? {
|
||||||
b"" => {}
|
b"" => {}
|
||||||
st => break st
|
st => break st
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let st = unsafe {std::str::from_utf8_unchecked(st)};
|
let st = unsafe {std::str::from_utf8_unchecked(st)};
|
||||||
let nu = u16::from_str_radix(st, 10)?;
|
let nu = u16::from_str_radix(st, 10)?;
|
||||||
Ok(nu)
|
Ok(nu)
|
||||||
};
|
};
|
||||||
|
|
||||||
let width = get_num()?;
|
let width = get_num()?;
|
||||||
let height = get_num()?;
|
let height = get_num()?;
|
||||||
let depth = i64::from(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 {
|
for _ in 0..height * width {
|
||||||
let r = FixedLong::from_int(get_num()?.into());
|
let r = FixedLong::from_int(get_num()?.into());
|
||||||
let g = FixedLong::from_int(get_num()?.into());
|
let g = FixedLong::from_int(get_num()?.into());
|
||||||
let b = FixedLong::from_int(get_num()?.into());
|
let b = FixedLong::from_int(get_num()?.into());
|
||||||
|
|
||||||
let r = (r / depth * 0xFFFF).integ() as u16;
|
let r = (r / depth * 0xFFFF).integ() as u16;
|
||||||
let g = (g / depth * 0xFFFF).integ() as u16;
|
let g = (g / depth * 0xFFFF).integ() as u16;
|
||||||
let b = (b / 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
|
// EOF
|
||||||
|
|
|
@ -10,32 +10,32 @@ use std::io;
|
||||||
/// Errors if `out` cannot be written to.
|
/// Errors if `out` cannot be written to.
|
||||||
pub fn write_tga(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
|
pub fn write_tga(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
|
||||||
{
|
{
|
||||||
// id len, color map type, image type
|
// id len, color map type, image type
|
||||||
out.write_all(&[0, 0, 2])?;
|
out.write_all(&[0, 0, 2])?;
|
||||||
// color map spec
|
// color map spec
|
||||||
out.write_all(&[0, 0, 0, 0, 0])?;
|
out.write_all(&[0, 0, 0, 0, 0])?;
|
||||||
// x origin
|
// x origin
|
||||||
out.write_all(&[0, 0])?;
|
out.write_all(&[0, 0])?;
|
||||||
// y origin
|
// y origin
|
||||||
out.write_all(&[0, 0])?;
|
out.write_all(&[0, 0])?;
|
||||||
// width
|
// width
|
||||||
out.write_all(&u16::to_le_bytes(im.w() as u16))?;
|
out.write_all(&u16::to_le_bytes(im.w() as u16))?;
|
||||||
// height
|
// height
|
||||||
out.write_all(&u16::to_le_bytes(im.h() as u16))?;
|
out.write_all(&u16::to_le_bytes(im.h() as u16))?;
|
||||||
// depth, descriptor
|
// depth, descriptor
|
||||||
out.write_all(&[32, 0])?;
|
out.write_all(&[32, 0])?;
|
||||||
|
|
||||||
for y in (0..im.h()).rev() {
|
for y in (0..im.h()).rev() {
|
||||||
for x in 0..im.w() {
|
for x in 0..im.w() {
|
||||||
let cr = im.index(x, y);
|
let cr = im.index(x, y);
|
||||||
out.write_all(&[(cr.b() >> 8) as u8,
|
out.write_all(&[(cr.b() >> 8) as u8,
|
||||||
(cr.g() >> 8) as u8,
|
(cr.g() >> 8) as u8,
|
||||||
(cr.r() >> 8) as u8,
|
(cr.r() >> 8) as u8,
|
||||||
(cr.a() >> 8) as u8])?;
|
(cr.a() >> 8) as u8])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,112 +5,112 @@ use std::io::{SeekFrom, prelude::*};
|
||||||
|
|
||||||
/// Skips over an Apple Single header. Returns true if one was found.
|
/// Skips over an Apple Single header. Returns true if one was found.
|
||||||
pub fn skip_apple_single<R>(fp: &mut R) -> bool
|
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 mut magic = [0; 8];
|
||||||
let magic = if fp.read(&mut magic).is_ok() {magic} else {return false;};
|
let magic = if fp.read(&mut magic).is_ok() {magic} else {return false;};
|
||||||
|
|
||||||
// check magic numbers
|
// check magic numbers
|
||||||
if magic != [0, 5, 22, 0, 0, 2, 0, 0] {
|
if magic != [0, 5, 22, 0, 0, 2, 0, 0] {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut num = [0; 2];
|
let mut num = [0; 2];
|
||||||
let num = if fp.read(&mut num).is_ok() {num} else {return false;};
|
let num = if fp.read(&mut num).is_ok() {num} else {return false;};
|
||||||
let num = u64::from(u16::from_be_bytes(num));
|
let num = u64::from(u16::from_be_bytes(num));
|
||||||
|
|
||||||
if fp.seek(SeekFrom::Start(26 + 12 * num)).is_err() |
|
if fp.seek(SeekFrom::Start(26 + 12 * num)).is_err() |
|
||||||
fp.seek(SeekFrom::Start(26)).is_err() {
|
fp.seek(SeekFrom::Start(26)).is_err() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the resource fork (entity 1)
|
// get the resource fork (entity 1)
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let mut ent = [0; 4];
|
let mut ent = [0; 4];
|
||||||
let mut ofs = [0; 4];
|
let mut ofs = [0; 4];
|
||||||
let mut len = [0; 4];
|
let mut len = [0; 4];
|
||||||
let ent = if fp.read(&mut ent).is_ok() {ent} else {return false;};
|
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 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 len = if fp.read(&mut len).is_ok() {len} else {return false;};
|
||||||
let ent = u32::from_be_bytes(ent);
|
let ent = u32::from_be_bytes(ent);
|
||||||
let ofs = u64::from(u32::from_be_bytes(ofs));
|
let ofs = u64::from(u32::from_be_bytes(ofs));
|
||||||
let len = u64::from(u32::from_be_bytes(len));
|
let len = u64::from(u32::from_be_bytes(len));
|
||||||
|
|
||||||
if ent == 1 {
|
if ent == 1 {
|
||||||
if fp.seek(SeekFrom::Start(ofs + len)).is_ok() &
|
if fp.seek(SeekFrom::Start(ofs + len)).is_ok() &
|
||||||
fp.seek(SeekFrom::Start(ofs)).is_ok() {
|
fp.seek(SeekFrom::Start(ofs)).is_ok() {
|
||||||
fp.set_seek(false);
|
fp.set_seek(false);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no resource fork
|
// no resource fork
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skips over a Mac Binary II header. Returns true if one was found.
|
/// Skips over a Mac Binary II header. Returns true if one was found.
|
||||||
pub fn skip_macbin<R>(fp: &mut R) -> bool
|
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 mut head = [0; 128];
|
||||||
let head = if fp.read(&mut head).is_ok() {head} else {return false;};
|
let head = if fp.read(&mut head).is_ok() {head} else {return false;};
|
||||||
|
|
||||||
// check legacy version, length, zero fill, and macbin2 version. I swear,
|
// check legacy version, length, zero fill, and macbin2 version. I swear,
|
||||||
// this isn't *completely* magic
|
// this isn't *completely* magic
|
||||||
if head[0] != 0 || head[1] > 63 || head[74] != 0 || head[123] > 129 {
|
if head[0] != 0 || head[1] > 63 || head[74] != 0 || head[123] > 129 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut crc = 0;
|
let mut crc = 0;
|
||||||
|
|
||||||
// check header crc
|
// check header crc
|
||||||
for &byte in head.iter().take(124) {
|
for &byte in head.iter().take(124) {
|
||||||
for j in 8..16 {
|
for j in 8..16 {
|
||||||
let d = u16::from(byte) << j;
|
let d = u16::from(byte) << j;
|
||||||
|
|
||||||
if (d ^ crc) & 0x8000 == 0 {
|
if (d ^ crc) & 0x8000 == 0 {
|
||||||
crc <<= 1;
|
crc <<= 1;
|
||||||
} else {
|
} else {
|
||||||
crc = crc << 1 ^ 0x1021;
|
crc = crc << 1 ^ 0x1021;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ok, resource fork follows
|
// if ok, resource fork follows
|
||||||
if crc == u16::from_be_bytes([head[124], head[125]]) {
|
if crc == u16::from_be_bytes([head[124], head[125]]) {
|
||||||
fp.set_seek(false);
|
fp.set_seek(false);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a `MacBin` or `AppleSingle` header if there is one and skips past it
|
/// 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
|
/// from the start of the header to the resource fork (if one is found.) Returns
|
||||||
/// true if either one was found.
|
/// true if either one was found.
|
||||||
pub fn skip_mac_header<R>(fp: &mut R) -> bool
|
pub fn skip_mac_header<R>(fp: &mut R) -> bool
|
||||||
where R: Read + Seek
|
where R: Read + Seek
|
||||||
{
|
{
|
||||||
if skip_macbin(fp) {
|
if skip_macbin(fp) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = fp.seek(SeekFrom::Start(0));
|
let _ = fp.seek(SeekFrom::Start(0));
|
||||||
|
|
||||||
if skip_apple_single(fp) {
|
if skip_apple_single(fp) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = fp.seek(SeekFrom::Start(0));
|
let _ = fp.seek(SeekFrom::Start(0));
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,22 +5,22 @@ use crate::err::*;
|
||||||
/// Reads an `ambi` chunk.
|
/// Reads an `ambi` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(SoundAmbi, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||||
let index = u16[2];
|
let index = u16[2];
|
||||||
let volume = u16[4];
|
let volume = u16[4];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((SoundAmbi{index, volume}, 16))
|
Ok((SoundAmbi{index, volume}, 16))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An ambient sound definition.
|
/// An ambient sound definition.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct SoundAmbi {
|
pub struct SoundAmbi {
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
pub volume: u16,
|
pub volume: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,34 +5,34 @@ use crate::{bin::OptU16, err::*, fixed::{Angle, Unit}};
|
||||||
/// Reads an `Attack` object.
|
/// Reads an `Attack` object.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Attack>
|
pub fn read(b: &[u8]) -> ResultS<Attack>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||||
let ptype = OptU16[0];
|
let ptype = OptU16[0];
|
||||||
let rep = u16[2];
|
let rep = u16[2];
|
||||||
let error = Angle[4];
|
let error = Angle[4];
|
||||||
let range = Unit[6];
|
let range = Unit[6];
|
||||||
let shape = u16[8];
|
let shape = u16[8];
|
||||||
let ofs_x = Unit[10];
|
let ofs_x = Unit[10];
|
||||||
let ofs_y = Unit[12];
|
let ofs_y = Unit[12];
|
||||||
let ofs_z = Unit[14];
|
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.
|
/// The definition of a monster's attack.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Attack {
|
pub struct Attack {
|
||||||
pub ptype: OptU16,
|
pub ptype: OptU16,
|
||||||
pub rep: u16,
|
pub rep: u16,
|
||||||
pub error: Angle,
|
pub error: Angle,
|
||||||
pub range: Unit,
|
pub range: Unit,
|
||||||
pub shape: u16,
|
pub shape: u16,
|
||||||
pub ofs_x: Unit,
|
pub ofs_x: Unit,
|
||||||
pub ofs_y: Unit,
|
pub ofs_y: Unit,
|
||||||
pub ofs_z: Unit,
|
pub ofs_z: Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,48 +5,48 @@ use crate::{err::*, fixed::{Angle, Fixed}};
|
||||||
/// Reads a `bonk` chunk.
|
/// Reads a `bonk` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(SoundRand, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(SoundRand, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||||
let flags = u16[0] flag SoundRandFlags;
|
let flags = u16[0] flag SoundRandFlags;
|
||||||
let index = u16[2];
|
let index = u16[2];
|
||||||
let vol_nrm = u16[4];
|
let vol_nrm = u16[4];
|
||||||
let vol_dta = u16[6];
|
let vol_dta = u16[6];
|
||||||
let prd_nrm = u16[8];
|
let prd_nrm = u16[8];
|
||||||
let prd_dta = u16[10];
|
let prd_dta = u16[10];
|
||||||
let yaw_nrm = Angle[12];
|
let yaw_nrm = Angle[12];
|
||||||
let yaw_dta = Angle[14];
|
let yaw_dta = Angle[14];
|
||||||
let pit_nrm = Fixed[16];
|
let pit_nrm = Fixed[16];
|
||||||
let pit_dta = Fixed[20];
|
let pit_dta = Fixed[20];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((SoundRand{flags, index, vol_nrm, vol_dta, prd_nrm, prd_dta, yaw_nrm,
|
Ok((SoundRand{flags, index, vol_nrm, vol_dta, prd_nrm, prd_dta, yaw_nrm,
|
||||||
yaw_dta, pit_nrm, pit_dta}, 32))
|
yaw_dta, pit_nrm, pit_dta}, 32))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A randomly played sound definition.
|
/// A randomly played sound definition.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct SoundRand {
|
pub struct SoundRand {
|
||||||
pub flags: SoundRandFlags,
|
pub flags: SoundRandFlags,
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
pub vol_nrm: u16,
|
pub vol_nrm: u16,
|
||||||
pub vol_dta: u16,
|
pub vol_dta: u16,
|
||||||
pub prd_nrm: u16,
|
pub prd_nrm: u16,
|
||||||
pub prd_dta: u16,
|
pub prd_dta: u16,
|
||||||
pub yaw_nrm: Angle,
|
pub yaw_nrm: Angle,
|
||||||
pub yaw_dta: Angle,
|
pub yaw_dta: Angle,
|
||||||
pub pit_nrm: Fixed,
|
pub pit_nrm: Fixed,
|
||||||
pub pit_dta: Fixed,
|
pub pit_dta: Fixed,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `SoundRand`.
|
/// Flags for `SoundRand`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct SoundRandFlags: u16 {
|
pub struct SoundRandFlags: u16 {
|
||||||
NO_DIRECTION = 0,
|
NO_DIRECTION = 0,
|
||||||
_2 = 1,
|
_2 = 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,99 +5,99 @@ use crate::{err::*, fixed::Fixed};
|
||||||
/// Reads a `Damage` object.
|
/// Reads a `Damage` object.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Damage>
|
pub fn read(b: &[u8]) -> ResultS<Damage>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 12, start: 0, data {
|
endian: BIG, buf: b, size: 12, start: 0, data {
|
||||||
let dtype = u16[0] enum DamageType;
|
let dtype = u16[0] enum DamageType;
|
||||||
let flags = u16[2] flag DamageFlags;
|
let flags = u16[2] flag DamageFlags;
|
||||||
let dmg_base = u16[4];
|
let dmg_base = u16[4];
|
||||||
let dmg_rand = u16[6];
|
let dmg_rand = u16[6];
|
||||||
let scale = Fixed[8];
|
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.
|
/// A damage definition.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Damage {
|
pub struct Damage {
|
||||||
pub dtype: DamageType,
|
pub dtype: DamageType,
|
||||||
pub flags: DamageFlags,
|
pub flags: DamageFlags,
|
||||||
pub dmg_base: u16,
|
pub dmg_base: u16,
|
||||||
pub dmg_rand: u16,
|
pub dmg_rand: u16,
|
||||||
pub scale: Fixed,
|
pub scale: Fixed,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// The composite type of damage taken by something.
|
/// The composite type of damage taken by something.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct DamageTypeFlags: u32 {
|
pub struct DamageTypeFlags: u32 {
|
||||||
EXPLOSION = 0,
|
EXPLOSION = 0,
|
||||||
ELECTRICAL_STAFF = 1,
|
ELECTRICAL_STAFF = 1,
|
||||||
PROJECTILE = 2,
|
PROJECTILE = 2,
|
||||||
ABSORBED = 3,
|
ABSORBED = 3,
|
||||||
FLAME = 4,
|
FLAME = 4,
|
||||||
HOUND_CLAWS = 5,
|
HOUND_CLAWS = 5,
|
||||||
ALIEN_PROJECTILE = 6,
|
ALIEN_PROJECTILE = 6,
|
||||||
HULK_SLAP = 7,
|
HULK_SLAP = 7,
|
||||||
COMPILER_BOLT = 8,
|
COMPILER_BOLT = 8,
|
||||||
FUSION_BOLT = 9,
|
FUSION_BOLT = 9,
|
||||||
HUNTER_BOLT = 10,
|
HUNTER_BOLT = 10,
|
||||||
FIST = 11,
|
FIST = 11,
|
||||||
TELEPORTER = 12,
|
TELEPORTER = 12,
|
||||||
DEFENDER = 13,
|
DEFENDER = 13,
|
||||||
YETI_CLAWS = 14,
|
YETI_CLAWS = 14,
|
||||||
YETI_PROJECTILE = 15,
|
YETI_PROJECTILE = 15,
|
||||||
CRUSHING = 16,
|
CRUSHING = 16,
|
||||||
LAVA = 17,
|
LAVA = 17,
|
||||||
SUFFOCATION = 18,
|
SUFFOCATION = 18,
|
||||||
GOO = 19,
|
GOO = 19,
|
||||||
ENERGY_DRAIN = 20,
|
ENERGY_DRAIN = 20,
|
||||||
OXYGEN_DRAIN = 21,
|
OXYGEN_DRAIN = 21,
|
||||||
HUMMER_BOLT = 22,
|
HUMMER_BOLT = 22,
|
||||||
SHOTGUN_PROJECTILE = 23,
|
SHOTGUN_PROJECTILE = 23,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Damage`.
|
/// Flags for `Damage`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct DamageFlags: u16 {
|
pub struct DamageFlags: u16 {
|
||||||
ALIEN = 0,
|
ALIEN = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// A named type of damage taken by something.
|
/// A named type of damage taken by something.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum DamageType: u16 {
|
pub enum DamageType: u16 {
|
||||||
Explosion = 0,
|
Explosion = 0,
|
||||||
ElectricalStaff = 1,
|
ElectricalStaff = 1,
|
||||||
Projectile = 2,
|
Projectile = 2,
|
||||||
Absorbed = 3,
|
Absorbed = 3,
|
||||||
Flame = 4,
|
Flame = 4,
|
||||||
HoundClaws = 5,
|
HoundClaws = 5,
|
||||||
AlienProjectile = 6,
|
AlienProjectile = 6,
|
||||||
HulkSlap = 7,
|
HulkSlap = 7,
|
||||||
CompilerBolt = 8,
|
CompilerBolt = 8,
|
||||||
FusionBolt = 9,
|
FusionBolt = 9,
|
||||||
HunterBolt = 10,
|
HunterBolt = 10,
|
||||||
Fist = 11,
|
Fist = 11,
|
||||||
Teleporter = 12,
|
Teleporter = 12,
|
||||||
Defender = 13,
|
Defender = 13,
|
||||||
YetiClaws = 14,
|
YetiClaws = 14,
|
||||||
YetiProjectile = 15,
|
YetiProjectile = 15,
|
||||||
Crushing = 16,
|
Crushing = 16,
|
||||||
Lava = 17,
|
Lava = 17,
|
||||||
Suffocation = 18,
|
Suffocation = 18,
|
||||||
Goo = 19,
|
Goo = 19,
|
||||||
EnergyDrain = 20,
|
EnergyDrain = 20,
|
||||||
OxygenDrain = 21,
|
OxygenDrain = 21,
|
||||||
HummerBolt = 22,
|
HummerBolt = 22,
|
||||||
ShotgunProjectile = 23,
|
ShotgunProjectile = 23,
|
||||||
None = 0xFFFF,
|
None = 0xFFFF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,187 +7,187 @@ use std::collections::BTreeMap;
|
||||||
/// Reads all chunks in an entry.
|
/// Reads all chunks in an entry.
|
||||||
pub fn read(head: &head::Header, b: &[u8]) -> ResultS<EntryData>
|
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_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_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_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_clite = if old {map::lite::read_old} else {map::lite::read};
|
||||||
|
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
while p < b.len() {
|
while p < b.len() {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: head.size_chunk(), start: p, data {
|
endian: BIG, buf: b, size: head.size_chunk(), start: p, data {
|
||||||
let iden = Ident[0];
|
let iden = Ident[0];
|
||||||
let size = u32[8] usize;
|
let size = u32[8] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let beg = p + head.size_chunk();
|
let beg = p + head.size_chunk();
|
||||||
let end = beg + size;
|
let end = beg + size;
|
||||||
let buf = ok!(b.get(beg..end), "not enough data")?;
|
let buf = ok!(b.get(beg..end), "not enough data")?;
|
||||||
|
|
||||||
match &iden.0 {
|
match &iden.0 {
|
||||||
b"EPNT" => data.epnt = Some(rd_array(buf, map::epnt::read)?),
|
b"EPNT" => data.epnt = Some(rd_array(buf, map::epnt::read)?),
|
||||||
b"FXpx" => data.fxpx = Some(rd_array(buf, map::fxpx::read)?),
|
b"FXpx" => data.fxpx = Some(rd_array(buf, map::fxpx::read)?),
|
||||||
b"LINS" => data.lins = Some(rd_array(buf, map::lins::read)?),
|
b"LINS" => data.lins = Some(rd_array(buf, map::lins::read)?),
|
||||||
b"LITE" => data.lite = Some(rd_array(buf, rd_clite)?),
|
b"LITE" => data.lite = Some(rd_array(buf, rd_clite)?),
|
||||||
b"MNpx" => data.mnpx = Some(rd_array(buf, map::mnpx::read)?),
|
b"MNpx" => data.mnpx = Some(rd_array(buf, map::mnpx::read)?),
|
||||||
b"Minf" => data.minf = Some(rd_cminf(buf)?),
|
b"Minf" => data.minf = Some(rd_cminf(buf)?),
|
||||||
b"NAME" => data.name = Some(rd_array(buf, map::name::read)?),
|
b"NAME" => data.name = Some(rd_array(buf, map::name::read)?),
|
||||||
b"NOTE" => data.note = Some(rd_array(buf, map::note::read)?),
|
b"NOTE" => data.note = Some(rd_array(buf, map::note::read)?),
|
||||||
b"OBJS" => data.objs = Some(rd_array(buf, map::objs::read)?),
|
b"OBJS" => data.objs = Some(rd_array(buf, map::objs::read)?),
|
||||||
b"PICT" => data.pict = Some(pict::read(buf)?),
|
b"PICT" => data.pict = Some(pict::read(buf)?),
|
||||||
b"PNTS" => data.pnts = Some(rd_array(buf, map::pnts::read)?),
|
b"PNTS" => data.pnts = Some(rd_array(buf, map::pnts::read)?),
|
||||||
b"POLY" => data.poly = Some(rd_array(buf, rd_cpoly)?),
|
b"POLY" => data.poly = Some(rd_array(buf, rd_cpoly)?),
|
||||||
b"PRpx" => data.prpx = Some(rd_array(buf, map::prpx::read)?),
|
b"PRpx" => data.prpx = Some(rd_array(buf, map::prpx::read)?),
|
||||||
b"PXpx" => data.pxpx = Some(rd_array(buf, map::pxpx::read)?),
|
b"PXpx" => data.pxpx = Some(rd_array(buf, map::pxpx::read)?),
|
||||||
b"SIDS" => data.sids = Some(rd_array(buf, rd_csids)?),
|
b"SIDS" => data.sids = Some(rd_array(buf, rd_csids)?),
|
||||||
b"WPpx" => data.wppx = Some(rd_array(buf, map::wppx::read)?),
|
b"WPpx" => data.wppx = Some(rd_array(buf, map::wppx::read)?),
|
||||||
b"ambi" => data.ambi = Some(rd_array(buf, map::ambi::read)?),
|
b"ambi" => data.ambi = Some(rd_array(buf, map::ambi::read)?),
|
||||||
b"bonk" => data.bonk = Some(rd_array(buf, map::bonk::read)?),
|
b"bonk" => data.bonk = Some(rd_array(buf, map::bonk::read)?),
|
||||||
b"iidx" => data.iidx = Some(rd_array(buf, map::iidx::read)?),
|
b"iidx" => data.iidx = Some(rd_array(buf, map::iidx::read)?),
|
||||||
b"medi" => data.medi = Some(rd_array(buf, map::medi::read)?),
|
b"medi" => data.medi = Some(rd_array(buf, map::medi::read)?),
|
||||||
b"plac" => data.plac = Some(rd_array(buf, map::plac::read)?),
|
b"plac" => data.plac = Some(rd_array(buf, map::plac::read)?),
|
||||||
b"plat" => data.plat = Some(rd_array(buf, map::plat::read)?),
|
b"plat" => data.plat = Some(rd_array(buf, map::plat::read)?),
|
||||||
b"term" => data.term = Some(rd_array(buf, map::term::read)?),
|
b"term" => data.term = Some(rd_array(buf, map::term::read)?),
|
||||||
_ => data.unkn.push((iden, buf.to_vec())),
|
_ => data.unkn.push((iden, buf.to_vec())),
|
||||||
}
|
}
|
||||||
|
|
||||||
p = end;
|
p = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads all of the data from an entry map.
|
/// Reads all of the data from an entry map.
|
||||||
pub fn read_all(head: &head::Header,
|
pub fn read_all(head: &head::Header,
|
||||||
map: &entr::EntryMap<'_>) -> ResultS<EntryDataMap>
|
map: &entr::EntryMap<'_>) -> ResultS<EntryDataMap>
|
||||||
{
|
{
|
||||||
let mut data_map = EntryDataMap::new();
|
let mut data_map = EntryDataMap::new();
|
||||||
|
|
||||||
for (&index, entry) in map {
|
for (&index, entry) in map {
|
||||||
data_map.insert(index, read(head, entry.data)?);
|
data_map.insert(index, read(head, entry.data)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(data_map)
|
Ok(data_map)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EntryData
|
impl EntryData
|
||||||
{
|
{
|
||||||
pub fn get_type(&self) -> EntryType
|
pub fn get_type(&self) -> EntryType
|
||||||
{
|
{
|
||||||
if self.has_minf() {
|
if self.has_minf() {
|
||||||
EntryType::Map
|
EntryType::Map
|
||||||
} else if self.has_fxpx() ||
|
} else if self.has_fxpx() ||
|
||||||
self.has_mnpx() ||
|
self.has_mnpx() ||
|
||||||
self.has_prpx() ||
|
self.has_prpx() ||
|
||||||
self.has_pxpx() ||
|
self.has_pxpx() ||
|
||||||
self.has_wppx() {
|
self.has_wppx() {
|
||||||
EntryType::Physics
|
EntryType::Physics
|
||||||
} else if self.has_pict() {
|
} else if self.has_pict() {
|
||||||
EntryType::Image
|
EntryType::Image
|
||||||
} else {
|
} else {
|
||||||
EntryType::Other
|
EntryType::Other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_epnt(&self) -> bool {self.epnt.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_fxpx(&self) -> bool {self.fxpx.is_some()}
|
||||||
pub fn has_lins(&self) -> bool {self.lins.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_lite(&self) -> bool {self.lite.is_some()}
|
||||||
pub fn has_mnpx(&self) -> bool {self.mnpx.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_minf(&self) -> bool {self.minf.is_some()}
|
||||||
pub fn has_name(&self) -> bool {self.name.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_note(&self) -> bool {self.note.is_some()}
|
||||||
pub fn has_objs(&self) -> bool {self.objs.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_pict(&self) -> bool {self.pict.is_some()}
|
||||||
pub fn has_pnts(&self) -> bool {self.pnts.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_poly(&self) -> bool {self.poly.is_some()}
|
||||||
pub fn has_prpx(&self) -> bool {self.prpx.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_pxpx(&self) -> bool {self.pxpx.is_some()}
|
||||||
pub fn has_sids(&self) -> bool {self.sids.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_wppx(&self) -> bool {self.wppx.is_some()}
|
||||||
pub fn has_ambi(&self) -> bool {self.ambi.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_bonk(&self) -> bool {self.bonk.is_some()}
|
||||||
pub fn has_iidx(&self) -> bool {self.iidx.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_medi(&self) -> bool {self.medi.is_some()}
|
||||||
pub fn has_plac(&self) -> bool {self.plac.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_plat(&self) -> bool {self.plat.is_some()}
|
||||||
pub fn has_term(&self) -> bool {self.term.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
|
pub fn len(&self) -> usize
|
||||||
{
|
{
|
||||||
self.num_unknown() +
|
self.num_unknown() +
|
||||||
usize::from(self.has_epnt()) +
|
usize::from(self.has_epnt()) +
|
||||||
usize::from(self.has_fxpx()) +
|
usize::from(self.has_fxpx()) +
|
||||||
usize::from(self.has_lins()) +
|
usize::from(self.has_lins()) +
|
||||||
usize::from(self.has_lite()) +
|
usize::from(self.has_lite()) +
|
||||||
usize::from(self.has_mnpx()) +
|
usize::from(self.has_mnpx()) +
|
||||||
usize::from(self.has_minf()) +
|
usize::from(self.has_minf()) +
|
||||||
usize::from(self.has_name()) +
|
usize::from(self.has_name()) +
|
||||||
usize::from(self.has_note()) +
|
usize::from(self.has_note()) +
|
||||||
usize::from(self.has_objs()) +
|
usize::from(self.has_objs()) +
|
||||||
usize::from(self.has_pict()) +
|
usize::from(self.has_pict()) +
|
||||||
usize::from(self.has_pnts()) +
|
usize::from(self.has_pnts()) +
|
||||||
usize::from(self.has_poly()) +
|
usize::from(self.has_poly()) +
|
||||||
usize::from(self.has_prpx()) +
|
usize::from(self.has_prpx()) +
|
||||||
usize::from(self.has_pxpx()) +
|
usize::from(self.has_pxpx()) +
|
||||||
usize::from(self.has_sids()) +
|
usize::from(self.has_sids()) +
|
||||||
usize::from(self.has_wppx()) +
|
usize::from(self.has_wppx()) +
|
||||||
usize::from(self.has_ambi()) +
|
usize::from(self.has_ambi()) +
|
||||||
usize::from(self.has_bonk()) +
|
usize::from(self.has_bonk()) +
|
||||||
usize::from(self.has_iidx()) +
|
usize::from(self.has_iidx()) +
|
||||||
usize::from(self.has_medi()) +
|
usize::from(self.has_medi()) +
|
||||||
usize::from(self.has_plac()) +
|
usize::from(self.has_plac()) +
|
||||||
usize::from(self.has_plat())
|
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.
|
/// The abstract type of an entry.
|
||||||
pub enum EntryType {
|
pub enum EntryType {
|
||||||
Other,
|
Other,
|
||||||
Map,
|
Map,
|
||||||
Image,
|
Image,
|
||||||
Physics,
|
Physics,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The loaded data of a Map file entry.
|
/// The loaded data of a Map file entry.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Default, Eq, PartialEq)]
|
#[derive(Debug, Default, Eq, PartialEq)]
|
||||||
pub struct EntryData {
|
pub struct EntryData {
|
||||||
/** `EPNT` chunk data. */ pub epnt: Option<Vec<map::epnt::Endpoint>>,
|
/** `EPNT` chunk data. */ pub epnt: Option<Vec<map::epnt::Endpoint>>,
|
||||||
/** `FXpx` chunk data. */ pub fxpx: Option<Vec<map::fxpx::Effect>>,
|
/** `FXpx` chunk data. */ pub fxpx: Option<Vec<map::fxpx::Effect>>,
|
||||||
/** `LINS` chunk data. */ pub lins: Option<Vec<map::lins::Line>>,
|
/** `LINS` chunk data. */ pub lins: Option<Vec<map::lins::Line>>,
|
||||||
/** `LITE` chunk data. */ pub lite: Option<Vec<map::lite::Light>>,
|
/** `LITE` chunk data. */ pub lite: Option<Vec<map::lite::Light>>,
|
||||||
/** `MNpx` chunk data. */ pub mnpx: Option<Vec<map::mnpx::Monster>>,
|
/** `MNpx` chunk data. */ pub mnpx: Option<Vec<map::mnpx::Monster>>,
|
||||||
/** `Minf` chunk data. */ pub minf: Option<map::minf::Info>,
|
/** `Minf` chunk data. */ pub minf: Option<map::minf::Info>,
|
||||||
/** `NAME` chunk data. */ pub name: Option<Vec<String>>,
|
/** `NAME` chunk data. */ pub name: Option<Vec<String>>,
|
||||||
/** `NOTE` chunk data. */ pub note: Option<Vec<map::note::Note>>,
|
/** `NOTE` chunk data. */ pub note: Option<Vec<map::note::Note>>,
|
||||||
/** `OBJS` chunk data. */ pub objs: Option<Vec<map::objs::Object>>,
|
/** `OBJS` chunk data. */ pub objs: Option<Vec<map::objs::Object>>,
|
||||||
/** `PICT` chunk data. */ pub pict: Option<image::Image8>,
|
/** `PICT` chunk data. */ pub pict: Option<image::Image8>,
|
||||||
/** `PNTS` chunk data. */ pub pnts: Option<Vec<map::pnts::Point>>,
|
/** `PNTS` chunk data. */ pub pnts: Option<Vec<map::pnts::Point>>,
|
||||||
/** `POLY` chunk data. */ pub poly: Option<Vec<map::poly::Polygon>>,
|
/** `POLY` chunk data. */ pub poly: Option<Vec<map::poly::Polygon>>,
|
||||||
/** `PRpx` chunk data. */ pub prpx: Option<Vec<map::prpx::Projectile>>,
|
/** `PRpx` chunk data. */ pub prpx: Option<Vec<map::prpx::Projectile>>,
|
||||||
/** `PXpx` chunk data. */ pub pxpx: Option<Vec<map::pxpx::Physics>>,
|
/** `PXpx` chunk data. */ pub pxpx: Option<Vec<map::pxpx::Physics>>,
|
||||||
/** `SIDS` chunk data. */ pub sids: Option<Vec<map::sids::Side>>,
|
/** `SIDS` chunk data. */ pub sids: Option<Vec<map::sids::Side>>,
|
||||||
/** `WPpx` chunk data. */ pub wppx: Option<Vec<map::wppx::Weapon>>,
|
/** `WPpx` chunk data. */ pub wppx: Option<Vec<map::wppx::Weapon>>,
|
||||||
/** `ambi` chunk data. */ pub ambi: Option<Vec<map::ambi::SoundAmbi>>,
|
/** `ambi` chunk data. */ pub ambi: Option<Vec<map::ambi::SoundAmbi>>,
|
||||||
/** `bonk` chunk data. */ pub bonk: Option<Vec<map::bonk::SoundRand>>,
|
/** `bonk` chunk data. */ pub bonk: Option<Vec<map::bonk::SoundRand>>,
|
||||||
/** `iidx` chunk data. */ pub iidx: Option<Vec<u16>>,
|
/** `iidx` chunk data. */ pub iidx: Option<Vec<u16>>,
|
||||||
/** `medi` chunk data. */ pub medi: Option<Vec<map::medi::Media>>,
|
/** `medi` chunk data. */ pub medi: Option<Vec<map::medi::Media>>,
|
||||||
/** `plac` chunk data. */ pub plac: Option<Vec<map::plac::ObjectFreq>>,
|
/** `plac` chunk data. */ pub plac: Option<Vec<map::plac::ObjectFreq>>,
|
||||||
/** `plat` chunk data. */ pub plat: Option<Vec<map::plat::Platform>>,
|
/** `plat` chunk data. */ pub plat: Option<Vec<map::plat::Platform>>,
|
||||||
/** `term` chunk data. */ pub term: Option<Vec<map::term::Terminal>>,
|
/** `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.
|
/// A map of indexed entries.
|
||||||
|
|
|
@ -7,61 +7,61 @@ use std::collections::BTreeMap;
|
||||||
/// Read an entry from a Map file.
|
/// Read an entry from a Map file.
|
||||||
pub fn read(map: &head::Map, i: usize) -> ResultS<(u16, Entry<'_>)>
|
pub fn read(map: &head::Map, i: usize) -> ResultS<(u16, Entry<'_>)>
|
||||||
{
|
{
|
||||||
let size = map.head().size_entry();
|
let size = map.head().size_entry();
|
||||||
let b = map.dir();
|
let b = map.dir();
|
||||||
let sta = size * i;
|
let sta = size * i;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: size, start: sta, data {
|
endian: BIG, buf: b, size: size, start: sta, data {
|
||||||
let offset = u32[0] usize;
|
let offset = u32[0] usize;
|
||||||
let dsize = u32[4] usize;
|
let dsize = u32[4] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (index, app_data) = if !map.head().old_wad() {
|
let (index, app_data) = if !map.head().old_wad() {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: size, start: sta, data {
|
endian: BIG, buf: b, size: size, start: sta, data {
|
||||||
let index = u16[8];
|
let index = u16[8];
|
||||||
let app_data = u8[10; map.head().size_appl()];
|
let app_data = u8[10; map.head().size_appl()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(index, app_data)
|
(index, app_data)
|
||||||
} else {
|
} else {
|
||||||
(i as u16, &b[0..0])
|
(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.
|
/// Reads all entries in a Map file.
|
||||||
pub fn read_all(map: &head::Map) -> ResultS<EntryMap<'_>>
|
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() {
|
for i in 0..map.num_ent() {
|
||||||
let (index, entry) = read(map, i)?;
|
let (index, entry) = read(map, i)?;
|
||||||
|
|
||||||
if entries.contains_key(&index) {
|
if entries.contains_key(&index) {
|
||||||
bail!("entry index already exists");
|
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.
|
/// An entry containing chunked data and application-specific data.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Entry<'a> {
|
pub struct Entry<'a> {
|
||||||
/// The data in this `Entry`.
|
/// The data in this `Entry`.
|
||||||
pub data: &'a [u8],
|
pub data: &'a [u8],
|
||||||
|
|
||||||
/// The application specific data for this Entry.
|
/// The application specific data for this Entry.
|
||||||
pub app_data: &'a [u8],
|
pub app_data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A map of indexed entries.
|
/// A map of indexed entries.
|
||||||
|
|
|
@ -6,44 +6,44 @@ use crate::{err::*, fixed::Unit};
|
||||||
/// Reads an `EPNT` chunk.
|
/// Reads an `EPNT` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Endpoint, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Endpoint, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||||
let flags = u16[0] flag EndpointFlags;
|
let flags = u16[0] flag EndpointFlags;
|
||||||
let hei_hi = Unit[2];
|
let hei_hi = Unit[2];
|
||||||
let hei_lo = Unit[4];
|
let hei_lo = Unit[4];
|
||||||
let pos = pnts::read_o[6; 4];
|
let pos = pnts::read_o[6; 4];
|
||||||
let support = u16[10];
|
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.
|
/// Converts a vector of `Endpoint`s to a vector of `Point`s.
|
||||||
pub fn to_pnts(v: &[Endpoint]) -> Vec<pnts::Point>
|
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.
|
/// A pre-processed point in world-space.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Endpoint {
|
pub struct Endpoint {
|
||||||
pub flags: EndpointFlags,
|
pub flags: EndpointFlags,
|
||||||
pub hei_hi: Unit,
|
pub hei_hi: Unit,
|
||||||
pub hei_lo: Unit,
|
pub hei_lo: Unit,
|
||||||
pub pos: pnts::Point,
|
pub pos: pnts::Point,
|
||||||
pub support: u16,
|
pub support: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Endpoint`.
|
/// Flags for `Endpoint`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct EndpointFlags: u16 {
|
pub struct EndpointFlags: u16 {
|
||||||
SOLID = 0,
|
SOLID = 0,
|
||||||
SAME_HEIGHT = 1,
|
SAME_HEIGHT = 1,
|
||||||
TRANSPARENT = 2,
|
TRANSPARENT = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,42 +5,42 @@ use crate::{bin::OptU16, err::*, fixed::Fixed};
|
||||||
/// Reads a `FXpx` chunk.
|
/// Reads a `FXpx` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Effect, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Effect, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 14, start: 0, data {
|
endian: BIG, buf: b, size: 14, start: 0, data {
|
||||||
let collection = u16[0];
|
let collection = u16[0];
|
||||||
let shape = u16[2];
|
let shape = u16[2];
|
||||||
let pitch = Fixed[4];
|
let pitch = Fixed[4];
|
||||||
let flags = u16[8] flag EffectFlags;
|
let flags = u16[8] flag EffectFlags;
|
||||||
let delay = OptU16[10];
|
let delay = OptU16[10];
|
||||||
let delay_snd = OptU16[12];
|
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.
|
/// An effect definition.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Effect {
|
pub struct Effect {
|
||||||
pub collection: u16,
|
pub collection: u16,
|
||||||
pub shape: u16,
|
pub shape: u16,
|
||||||
pub pitch: Fixed,
|
pub pitch: Fixed,
|
||||||
pub flags: EffectFlags,
|
pub flags: EffectFlags,
|
||||||
pub delay: OptU16,
|
pub delay: OptU16,
|
||||||
pub delay_snd: OptU16,
|
pub delay_snd: OptU16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for an effect.
|
/// Flags for an effect.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct EffectFlags: u16 {
|
pub struct EffectFlags: u16 {
|
||||||
END_ON_LOOP = 0,
|
END_ON_LOOP = 0,
|
||||||
END_ON_XFER_LOOP = 1,
|
END_ON_XFER_LOOP = 1,
|
||||||
SOUND_ONLY = 2,
|
SOUND_ONLY = 2,
|
||||||
MAKE_TWIN_VISIBLE = 3,
|
MAKE_TWIN_VISIBLE = 3,
|
||||||
MEDIA_EFFECT = 4,
|
MEDIA_EFFECT = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,145 +6,145 @@ use std::io::prelude::*;
|
||||||
/// Reads a Map file.
|
/// Reads a Map file.
|
||||||
pub fn read(rd: &mut impl Read) -> ResultS<Map>
|
pub fn read(rd: &mut impl Read) -> ResultS<Map>
|
||||||
{
|
{
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
rd.read_to_end(&mut data)?;
|
rd.read_to_end(&mut data)?;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: &data, size: 128, start: 0, data {
|
endian: BIG, buf: &data, size: 128, start: 0, data {
|
||||||
let ver_wad = u16[0] enum Ver;
|
let ver_wad = u16[0] enum Ver;
|
||||||
let ver_data = u16[2];
|
let ver_data = u16[2];
|
||||||
let name = mac_roman_cstr[4; 64] no_try;
|
let name = mac_roman_cstr[4; 64] no_try;
|
||||||
let dir_ofs = u32[72] usize;
|
let dir_ofs = u32[72] usize;
|
||||||
let num_ent = u16[76] usize;
|
let num_ent = u16[76] usize;
|
||||||
let size_appl = u16[78] usize;
|
let size_appl = u16[78] usize;
|
||||||
let size_wcnk = u16[80] usize;
|
let size_wcnk = u16[80] usize;
|
||||||
let size_went = u16[82] 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 {
|
if !head.old_wad() && head.size_entry_base() != size_went {
|
||||||
bail!("invalid entry size");
|
bail!("invalid entry size");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !head.old_wad() && head.size_chunk() != size_wcnk {
|
if !head.old_wad() && head.size_chunk() != size_wcnk {
|
||||||
bail!("invalid chunk size");
|
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() {
|
if map.dir_end() > map.data.len() {
|
||||||
bail!("not enough data in map file");
|
bail!("not enough data in map file");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Header
|
impl Header
|
||||||
{
|
{
|
||||||
/// Creates a new `Header`.
|
/// Creates a new `Header`.
|
||||||
pub fn new(size_appl: usize,
|
pub fn new(size_appl: usize,
|
||||||
ver_data: u16,
|
ver_data: u16,
|
||||||
ver_wad: Ver,
|
ver_wad: Ver,
|
||||||
name: Option<String>) -> Self
|
name: Option<String>) -> Self
|
||||||
{
|
{
|
||||||
let name = name.unwrap_or_default();
|
let name = name.unwrap_or_default();
|
||||||
Self{name, size_appl, ver_data, ver_wad}
|
Self{name, size_appl, ver_data, ver_wad}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the data is in Marathon 1 format.
|
/// Returns `true` if the data is in Marathon 1 format.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn old_data(&self) -> bool {self.ver_data() == 0}
|
pub const fn old_data(&self) -> bool {self.ver_data() == 0}
|
||||||
|
|
||||||
/// Returns `true` if the Map file is in Marathon 1 format.
|
/// Returns `true` if the Map file is in Marathon 1 format.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn old_wad(&self) -> bool {self.ver_wad() == Ver::Base}
|
pub fn old_wad(&self) -> bool {self.ver_wad() == Ver::Base}
|
||||||
|
|
||||||
/// The data version of this file.
|
/// The data version of this file.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn ver_data(&self) -> u16 {self.ver_data}
|
pub const fn ver_data(&self) -> u16 {self.ver_data}
|
||||||
|
|
||||||
/// The format version of this file.
|
/// The format version of this file.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn ver_wad(&self) -> Ver {self.ver_wad}
|
pub const fn ver_wad(&self) -> Ver {self.ver_wad}
|
||||||
|
|
||||||
/// The size of each `Entry`'s `appdata` field.
|
/// The size of each `Entry`'s `appdata` field.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn size_appl(&self) -> usize {self.size_appl}
|
pub const fn size_appl(&self) -> usize {self.size_appl}
|
||||||
|
|
||||||
/// The size of each `Entry`'s data.
|
/// The size of each `Entry`'s data.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn size_entry_base(&self) -> usize {if self.old_wad() {8} else {10}}
|
pub fn size_entry_base(&self) -> usize {if self.old_wad() {8} else {10}}
|
||||||
|
|
||||||
/// The size of each `Entry`.
|
/// The size of each `Entry`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn size_entry(&self) -> usize {self.size_entry_base() + self.size_appl()}
|
pub fn size_entry(&self) -> usize {self.size_entry_base() + self.size_appl()}
|
||||||
|
|
||||||
/// The size of each chunk's header.
|
/// The size of each chunk's header.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn size_chunk(&self) -> usize {if self.old_wad() {12} else {16}}
|
pub fn size_chunk(&self) -> usize {if self.old_wad() {12} else {16}}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Map
|
impl Map
|
||||||
{
|
{
|
||||||
/// The header for this map.
|
/// The header for this map.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn head(&self) -> &Header {&self.head}
|
pub const fn head(&self) -> &Header {&self.head}
|
||||||
|
|
||||||
/// The data section of this map.
|
/// The data section of this map.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn data(&self) -> &[u8] {&self.data[..]}
|
pub fn data(&self) -> &[u8] {&self.data[..]}
|
||||||
|
|
||||||
/// The directory section of this map.
|
/// The directory section of this map.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dir(&self) -> &[u8] {&self.data[self.dir_beg()..self.dir_end()]}
|
pub fn dir(&self) -> &[u8] {&self.data[self.dir_beg()..self.dir_end()]}
|
||||||
|
|
||||||
/// The number of entries in the directory.
|
/// The number of entries in the directory.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn num_ent(&self) -> usize {self.num_ent}
|
pub const fn num_ent(&self) -> usize {self.num_ent}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn dir_beg(&self) -> usize {self.dir_ofs}
|
const fn dir_beg(&self) -> usize {self.dir_ofs}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn dir_end(&self) -> usize
|
fn dir_end(&self) -> usize
|
||||||
{
|
{
|
||||||
self.dir_ofs + self.head.size_entry() * self.num_ent
|
self.dir_ofs + self.head.size_entry() * self.num_ent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Map header.
|
/// A Map header.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
/// The original name of this file.
|
/// The original name of this file.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
size_appl: usize,
|
size_appl: usize,
|
||||||
ver_data: u16,
|
ver_data: u16,
|
||||||
ver_wad: Ver,
|
ver_wad: Ver,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Map file.
|
/// A Map file.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
head: Header,
|
head: Header,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
dir_ofs: usize,
|
dir_ofs: usize,
|
||||||
num_ent: usize,
|
num_ent: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The version of a Map file.
|
/// The version of a Map file.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum Ver: u16 {
|
pub enum Ver: u16 {
|
||||||
Base = 0,
|
Base = 0,
|
||||||
Dir = 1,
|
Dir = 1,
|
||||||
Over = 2,
|
Over = 2,
|
||||||
Inf = 4,
|
Inf = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,9 +5,9 @@ use crate::{bin::{check_data, u16b}, err::*};
|
||||||
/// Reads an `iidx` chunk.
|
/// Reads an `iidx` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(u16, usize)>
|
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
|
// EOF
|
||||||
|
|
|
@ -5,45 +5,45 @@ use crate::{bin::OptU16, err::*};
|
||||||
/// Reads a `LINS` chunk.
|
/// Reads a `LINS` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Line, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Line, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||||
let pnt_beg = u16[0];
|
let pnt_beg = u16[0];
|
||||||
let pnt_end = u16[2];
|
let pnt_end = u16[2];
|
||||||
let flags = u16[4] flag LineFlags;
|
let flags = u16[4] flag LineFlags;
|
||||||
let side_fr = OptU16[12];
|
let side_fr = OptU16[12];
|
||||||
let side_bk = OptU16[14];
|
let side_bk = OptU16[14];
|
||||||
let poly_fr = OptU16[16];
|
let poly_fr = OptU16[16];
|
||||||
let poly_bk = OptU16[18];
|
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.
|
/// A line segment.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Line {
|
pub struct Line {
|
||||||
pub flags: LineFlags,
|
pub flags: LineFlags,
|
||||||
pub pnt_beg: u16,
|
pub pnt_beg: u16,
|
||||||
pub pnt_end: u16,
|
pub pnt_end: u16,
|
||||||
pub side_fr: OptU16,
|
pub side_fr: OptU16,
|
||||||
pub side_bk: OptU16,
|
pub side_bk: OptU16,
|
||||||
pub poly_fr: OptU16,
|
pub poly_fr: OptU16,
|
||||||
pub poly_bk: OptU16,
|
pub poly_bk: OptU16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Line`.
|
/// Flags for `Line`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct LineFlags: u16 {
|
pub struct LineFlags: u16 {
|
||||||
TRANS_SIDE = 9,
|
TRANS_SIDE = 9,
|
||||||
ELEV_VAR = 10,
|
ELEV_VAR = 10,
|
||||||
ELEVATION = 11,
|
ELEVATION = 11,
|
||||||
LANDSCAPE = 12,
|
LANDSCAPE = 12,
|
||||||
TRANSPARENT = 13,
|
TRANSPARENT = 13,
|
||||||
SOLID = 14,
|
SOLID = 14,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,393 +6,393 @@ use crate::{err::*, fixed::Fixed};
|
||||||
/// Reads a `LITE` chunk.
|
/// Reads a `LITE` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Light, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Light, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 100, start: 0, data {
|
endian: BIG, buf: b, size: 100, start: 0, data {
|
||||||
let ltype = u16[0] enum LightType;
|
let ltype = u16[0] enum LightType;
|
||||||
let flags = u16[2] flag LightFlags;
|
let flags = u16[2] flag LightFlags;
|
||||||
let phase = i16[4];
|
let phase = i16[4];
|
||||||
let act_pri = ltfn::read[6; 14];
|
let act_pri = ltfn::read[6; 14];
|
||||||
let act_sec = ltfn::read[20; 14];
|
let act_sec = ltfn::read[20; 14];
|
||||||
let act_mid = ltfn::read[34; 14];
|
let act_mid = ltfn::read[34; 14];
|
||||||
let ina_pri = ltfn::read[48; 14];
|
let ina_pri = ltfn::read[48; 14];
|
||||||
let ina_sec = ltfn::read[62; 14];
|
let ina_sec = ltfn::read[62; 14];
|
||||||
let ina_mid = ltfn::read[76; 14];
|
let ina_mid = ltfn::read[76; 14];
|
||||||
let tag = u16[90];
|
let tag = u16[90];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec,
|
Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec,
|
||||||
ina_mid, tag}, 100))
|
ina_mid, tag}, 100))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an old `LITE` chunk.
|
/// Reads an old `LITE` chunk.
|
||||||
pub fn read_old(b: &[u8]) -> ResultS<(Light, usize)>
|
pub fn read_old(b: &[u8]) -> ResultS<(Light, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||||
let ltype = u16[2] usize;
|
let ltype = u16[2] usize;
|
||||||
let mode = u16[4];
|
let mode = u16[4];
|
||||||
let phase = i16[6];
|
let phase = i16[6];
|
||||||
let min = Fixed[8];
|
let min = Fixed[8];
|
||||||
let max = Fixed[12];
|
let max = Fixed[12];
|
||||||
let prd = u16[16];
|
let prd = u16[16];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if OLD_LIGHT_DEFINITIONS.len() < ltype {
|
if OLD_LIGHT_DEFINITIONS.len() < ltype {
|
||||||
bail!("bad old light type");
|
bail!("bad old light type");
|
||||||
}
|
}
|
||||||
|
|
||||||
let lite = &OLD_LIGHT_DEFINITIONS[ltype];
|
let lite = &OLD_LIGHT_DEFINITIONS[ltype];
|
||||||
let on = mode == 0 || mode == 1;
|
let on = mode == 0 || mode == 1;
|
||||||
let strobe = ltype == 3;
|
let strobe = ltype == 3;
|
||||||
let flags = if on {lite.flags | LightFlags::INIT_ACTIVE} else {lite.flags};
|
let flags = if on {lite.flags | LightFlags::INIT_ACTIVE} else {lite.flags};
|
||||||
|
|
||||||
// modify each old light function accordingly
|
// modify each old light function accordingly
|
||||||
let old_lfun = move |func: <fn::LightFunc| -> ltfn::LightFunc {
|
let old_lfun = move |func: <fn::LightFunc| -> ltfn::LightFunc {
|
||||||
ltfn::LightFunc{ftype: func.ftype,
|
ltfn::LightFunc{ftype: func.ftype,
|
||||||
prd_nrm: if strobe {prd / 4 + 1} else {func.prd_nrm},
|
prd_nrm: if strobe {prd / 4 + 1} else {func.prd_nrm},
|
||||||
prd_dta: func.prd_dta,
|
prd_dta: func.prd_dta,
|
||||||
val_nrm: if func.val_nrm > 0.into() {max} else {min},
|
val_nrm: if func.val_nrm > 0.into() {max} else {min},
|
||||||
val_dta: func.val_dta}
|
val_dta: func.val_dta}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((Light{flags,
|
Ok((Light{flags,
|
||||||
phase,
|
phase,
|
||||||
act_pri: old_lfun(&lite.act_pri),
|
act_pri: old_lfun(&lite.act_pri),
|
||||||
act_sec: old_lfun(&lite.act_sec),
|
act_sec: old_lfun(&lite.act_sec),
|
||||||
act_mid: old_lfun(&lite.act_mid),
|
act_mid: old_lfun(&lite.act_mid),
|
||||||
ina_pri: old_lfun(&lite.ina_pri),
|
ina_pri: old_lfun(&lite.ina_pri),
|
||||||
ina_sec: old_lfun(&lite.ina_sec),
|
ina_sec: old_lfun(&lite.ina_sec),
|
||||||
ina_mid: old_lfun(&lite.ina_mid),
|
ina_mid: old_lfun(&lite.ina_mid),
|
||||||
tag: 0,
|
tag: 0,
|
||||||
..*lite}, 32))
|
..*lite}, 32))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A dynamic polygon light.
|
/// A dynamic polygon light.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Light {
|
pub struct Light {
|
||||||
pub ltype: LightType,
|
pub ltype: LightType,
|
||||||
pub flags: LightFlags,
|
pub flags: LightFlags,
|
||||||
pub phase: i16,
|
pub phase: i16,
|
||||||
pub act_pri: ltfn::LightFunc,
|
pub act_pri: ltfn::LightFunc,
|
||||||
pub act_sec: ltfn::LightFunc,
|
pub act_sec: ltfn::LightFunc,
|
||||||
pub act_mid: ltfn::LightFunc,
|
pub act_mid: ltfn::LightFunc,
|
||||||
pub ina_pri: ltfn::LightFunc,
|
pub ina_pri: ltfn::LightFunc,
|
||||||
pub ina_sec: ltfn::LightFunc,
|
pub ina_sec: ltfn::LightFunc,
|
||||||
pub ina_mid: ltfn::LightFunc,
|
pub ina_mid: ltfn::LightFunc,
|
||||||
pub tag: u16,
|
pub tag: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Light`.
|
/// Flags for `Light`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct LightFlags: u16 {
|
pub struct LightFlags: u16 {
|
||||||
INIT_ACTIVE = 0,
|
INIT_ACTIVE = 0,
|
||||||
SLAVE_VALUE = 1,
|
SLAVE_VALUE = 1,
|
||||||
STATELESS = 2,
|
STATELESS = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The type of a `Light`.
|
/// The type of a `Light`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum LightType: u16 {
|
pub enum LightType: u16 {
|
||||||
Normal = 0,
|
Normal = 0,
|
||||||
Strobe = 1,
|
Strobe = 1,
|
||||||
Media = 2,
|
Media = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const OLD_LIGHT_DEFINITIONS: [Light; 8] = [
|
const OLD_LIGHT_DEFINITIONS: [Light; 8] = [
|
||||||
// Normal
|
// Normal
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: 1,
|
prd_nrm: 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: 1,
|
prd_nrm: 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
|
|
||||||
// Rheostat
|
// Rheostat
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 3,
|
prd_nrm: TICKS_PER_SECOND * 3,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 3,
|
prd_nrm: TICKS_PER_SECOND * 3,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
|
|
||||||
// Flourescent
|
// Flourescent
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Fluorescent,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Fluorescent,
|
||||||
prd_nrm: TICKS_PER_SECOND * 3,
|
prd_nrm: TICKS_PER_SECOND * 3,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: 1,
|
prd_nrm: 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
|
|
||||||
// Strobe
|
// Strobe
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: 1,
|
prd_nrm: 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: 1,
|
prd_nrm: 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
|
|
||||||
// Flicker
|
// Flicker
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Flicker,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Flicker,
|
||||||
prd_nrm: TICKS_PER_SECOND * 3,
|
prd_nrm: TICKS_PER_SECOND * 3,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: 1,
|
prd_nrm: 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
|
|
||||||
// Pulsate
|
// Pulsate
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2,
|
prd_nrm: TICKS_PER_SECOND * 2,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2,
|
prd_nrm: TICKS_PER_SECOND * 2,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
prd_nrm: TICKS_PER_SECOND * 2 - 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2,
|
prd_nrm: TICKS_PER_SECOND * 2,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
|
|
||||||
// Annoying
|
// Annoying
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
|
||||||
prd_nrm: 2,
|
prd_nrm: 2,
|
||||||
prd_dta: 1,
|
prd_dta: 1,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: 2,
|
prd_nrm: 2,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random,
|
||||||
prd_nrm: 1,
|
prd_nrm: 1,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
|
|
||||||
// Energy Efficient
|
// Energy Efficient
|
||||||
Light{ltype: LightType::Normal,
|
Light{ltype: LightType::Normal,
|
||||||
flags: LightFlags::SLAVE_VALUE,
|
flags: LightFlags::SLAVE_VALUE,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
|
act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2,
|
prd_nrm: TICKS_PER_SECOND * 2,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(1),
|
val_nrm: Fixed::from_int(1),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant,
|
||||||
prd_nrm: TICKS_PER_SECOND,
|
prd_nrm: TICKS_PER_SECOND,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
|
ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear,
|
||||||
prd_nrm: TICKS_PER_SECOND * 2,
|
prd_nrm: TICKS_PER_SECOND * 2,
|
||||||
prd_dta: 0,
|
prd_dta: 0,
|
||||||
val_nrm: Fixed::from_int(0),
|
val_nrm: Fixed::from_int(0),
|
||||||
val_dta: Fixed::from_int(0)},
|
val_dta: Fixed::from_int(0)},
|
||||||
tag: 0},
|
tag: 0},
|
||||||
];
|
];
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,53 +5,53 @@ use crate::{err::*, fixed::Fixed};
|
||||||
/// Reads a `LightFunc` object.
|
/// Reads a `LightFunc` object.
|
||||||
pub fn read(b: &[u8]) -> ResultS<LightFunc>
|
pub fn read(b: &[u8]) -> ResultS<LightFunc>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 14, start: 0, data {
|
endian: BIG, buf: b, size: 14, start: 0, data {
|
||||||
let ftype = u16[0] enum LightFuncType;
|
let ftype = u16[0] enum LightFuncType;
|
||||||
let prd_nrm = u16[2];
|
let prd_nrm = u16[2];
|
||||||
let prd_dta = u16[4];
|
let prd_dta = u16[4];
|
||||||
let val_nrm = Fixed[6];
|
let val_nrm = Fixed[6];
|
||||||
let val_dta = Fixed[10];
|
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.
|
/// Writes a `LightFunc` object.
|
||||||
pub fn write(v: &LightFunc) -> Vec<u8>
|
pub fn write(v: &LightFunc) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut o = Vec::with_capacity(14);
|
let mut o = Vec::with_capacity(14);
|
||||||
o.extend(&(v.ftype as u16).to_be_bytes());
|
o.extend(&(v.ftype as u16).to_be_bytes());
|
||||||
o.extend(&v.prd_nrm.to_be_bytes());
|
o.extend(&v.prd_nrm.to_be_bytes());
|
||||||
o.extend(&v.prd_dta.to_be_bytes());
|
o.extend(&v.prd_dta.to_be_bytes());
|
||||||
o.extend(&v.val_nrm.to_be_bytes());
|
o.extend(&v.val_nrm.to_be_bytes());
|
||||||
o.extend(&v.val_dta.to_be_bytes());
|
o.extend(&v.val_dta.to_be_bytes());
|
||||||
o
|
o
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A light function.
|
/// A light function.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct LightFunc {
|
pub struct LightFunc {
|
||||||
pub ftype: LightFuncType,
|
pub ftype: LightFuncType,
|
||||||
pub prd_nrm: u16,
|
pub prd_nrm: u16,
|
||||||
pub prd_dta: u16,
|
pub prd_dta: u16,
|
||||||
pub val_nrm: Fixed,
|
pub val_nrm: Fixed,
|
||||||
pub val_dta: Fixed,
|
pub val_dta: Fixed,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The type of function for a `LightFunc`.
|
/// The type of function for a `LightFunc`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum LightFuncType: u16 {
|
pub enum LightFuncType: u16 {
|
||||||
Constant = 0,
|
Constant = 0,
|
||||||
Linear = 1,
|
Linear = 1,
|
||||||
Smooth = 2,
|
Smooth = 2,
|
||||||
Flicker = 3,
|
Flicker = 3,
|
||||||
Random = 4,
|
Random = 4,
|
||||||
Fluorescent = 5,
|
Fluorescent = 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -9,63 +9,63 @@ use crate::{bin::OptU16,
|
||||||
/// Reads a `medi` chunk.
|
/// Reads a `medi` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Media, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Media, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||||
let mtype = u16[0] enum MediaType;
|
let mtype = u16[0] enum MediaType;
|
||||||
let flags = u8[3] flag MediaFlags;
|
let flags = u8[3] flag MediaFlags;
|
||||||
let control = u16[4];
|
let control = u16[4];
|
||||||
let dir = Angle[6];
|
let dir = Angle[6];
|
||||||
let mag = Unit[8];
|
let mag = Unit[8];
|
||||||
let hei_lo = Unit[10];
|
let hei_lo = Unit[10];
|
||||||
let hei_hi = Unit[12];
|
let hei_hi = Unit[12];
|
||||||
let orig = pnts::read_o[14; 4];
|
let orig = pnts::read_o[14; 4];
|
||||||
let hei_nrm = Unit[18];
|
let hei_nrm = Unit[18];
|
||||||
let min_lt = Fixed[20];
|
let min_lt = Fixed[20];
|
||||||
let texture = OptU16[24];
|
let texture = OptU16[24];
|
||||||
let xfer = u16[26] enum TransferMode;
|
let xfer = u16[26] enum TransferMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Media{mtype, flags, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm,
|
Ok((Media{mtype, flags, control, dir, mag, hei_lo, hei_hi, orig, hei_nrm,
|
||||||
min_lt, texture, xfer}, 32))
|
min_lt, texture, xfer}, 32))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A media, as in a part of a polygon which goes up the middle of the wall.
|
/// 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))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Media {
|
pub struct Media {
|
||||||
pub mtype: MediaType,
|
pub mtype: MediaType,
|
||||||
pub flags: MediaFlags,
|
pub flags: MediaFlags,
|
||||||
pub control: u16,
|
pub control: u16,
|
||||||
pub dir: Angle,
|
pub dir: Angle,
|
||||||
pub mag: Unit,
|
pub mag: Unit,
|
||||||
pub hei_lo: Unit,
|
pub hei_lo: Unit,
|
||||||
pub hei_hi: Unit,
|
pub hei_hi: Unit,
|
||||||
pub orig: pnts::Point,
|
pub orig: pnts::Point,
|
||||||
pub hei_nrm: Unit,
|
pub hei_nrm: Unit,
|
||||||
pub min_lt: Fixed,
|
pub min_lt: Fixed,
|
||||||
pub texture: OptU16,
|
pub texture: OptU16,
|
||||||
pub xfer: TransferMode,
|
pub xfer: TransferMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The liquid type of a `Media`.
|
/// The liquid type of a `Media`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum MediaType: u16 {
|
pub enum MediaType: u16 {
|
||||||
Water = 0,
|
Water = 0,
|
||||||
Lava = 1,
|
Lava = 1,
|
||||||
Goo = 2,
|
Goo = 2,
|
||||||
Sewage = 3,
|
Sewage = 3,
|
||||||
Jjaro = 4,
|
Jjaro = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Media`.
|
/// Flags for `Media`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct MediaFlags: u8 {
|
pub struct MediaFlags: u8 {
|
||||||
OBSTRUCT = 0,
|
OBSTRUCT = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,127 +5,127 @@ use crate::{err::*, text::*};
|
||||||
/// Reads a `Minf` chunk.
|
/// Reads a `Minf` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Info>
|
pub fn read(b: &[u8]) -> ResultS<Info>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 88, start: 0, data {
|
endian: BIG, buf: b, size: 88, start: 0, data {
|
||||||
let texture_id = u16[0];
|
let texture_id = u16[0];
|
||||||
let physics_id = u16[2];
|
let physics_id = u16[2];
|
||||||
let skypict_id = u16[4];
|
let skypict_id = u16[4];
|
||||||
let miss_flags = u16[6] flag MissionFlags;
|
let miss_flags = u16[6] flag MissionFlags;
|
||||||
let envi_flags = u16[8] flag EnvironmentFlags;
|
let envi_flags = u16[8] flag EnvironmentFlags;
|
||||||
let level_name = mac_roman_cstr[18; 66] no_try;
|
let level_name = mac_roman_cstr[18; 66] no_try;
|
||||||
let entr_flags = u32[84] flag EntryFlags;
|
let entr_flags = u32[84] flag EntryFlags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Info{texture_id, physics_id, skypict_id, miss_flags, envi_flags,
|
Ok(Info{texture_id, physics_id, skypict_id, miss_flags, envi_flags,
|
||||||
entr_flags, level_name})
|
entr_flags, level_name})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a `Minf` chunk.
|
/// Writes a `Minf` chunk.
|
||||||
pub fn write(v: &Info) -> Vec<u8>
|
pub fn write(v: &Info) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut o = Vec::with_capacity(4);
|
let mut o = Vec::with_capacity(4);
|
||||||
o.extend(&v.texture_id.to_be_bytes());
|
o.extend(&v.texture_id.to_be_bytes());
|
||||||
o.extend(&v.physics_id.to_be_bytes());
|
o.extend(&v.physics_id.to_be_bytes());
|
||||||
o.extend(&v.skypict_id.to_be_bytes());
|
o.extend(&v.skypict_id.to_be_bytes());
|
||||||
o.extend(&v.miss_flags.bits().to_be_bytes());
|
o.extend(&v.miss_flags.bits().to_be_bytes());
|
||||||
o.extend(&v.envi_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(&pad_zero(to_mac_roman(&v.level_name), 66));
|
||||||
o.extend(&v.entr_flags.bits().to_be_bytes());
|
o.extend(&v.entr_flags.bits().to_be_bytes());
|
||||||
o
|
o
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an old `Minf` chunk.
|
/// Reads an old `Minf` chunk.
|
||||||
pub fn read_old(b: &[u8]) -> ResultS<Info>
|
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() {
|
let mut entr_flags = if minf.entr_flags.is_empty() {
|
||||||
EntryFlags::SOLO
|
EntryFlags::SOLO
|
||||||
} else {
|
} else {
|
||||||
minf.entr_flags
|
minf.entr_flags
|
||||||
};
|
};
|
||||||
|
|
||||||
if entr_flags.intersects(EntryFlags::SOLO | EntryFlags::CARNAGE) {
|
if entr_flags.intersects(EntryFlags::SOLO | EntryFlags::CARNAGE) {
|
||||||
entr_flags.insert(EntryFlags::CO_OP)
|
entr_flags.insert(EntryFlags::CO_OP)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Info{entr_flags, ..minf})
|
Ok(Info{entr_flags, ..minf})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Info
|
impl Default for Info
|
||||||
{
|
{
|
||||||
fn default() -> Self
|
fn default() -> Self
|
||||||
{
|
{
|
||||||
Self{texture_id: 0,
|
Self{texture_id: 0,
|
||||||
physics_id: 1,
|
physics_id: 1,
|
||||||
skypict_id: 0,
|
skypict_id: 0,
|
||||||
miss_flags: MissionFlags::empty(),
|
miss_flags: MissionFlags::empty(),
|
||||||
envi_flags: EnvironmentFlags::empty(),
|
envi_flags: EnvironmentFlags::empty(),
|
||||||
entr_flags: EntryFlags::SOLO,
|
entr_flags: EntryFlags::SOLO,
|
||||||
level_name: "Map".to_string()}
|
level_name: "Map".to_string()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Static map information.
|
/// Static map information.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Info {
|
pub struct Info {
|
||||||
pub texture_id: u16,
|
pub texture_id: u16,
|
||||||
pub physics_id: u16,
|
pub physics_id: u16,
|
||||||
pub skypict_id: u16,
|
pub skypict_id: u16,
|
||||||
pub miss_flags: MissionFlags,
|
pub miss_flags: MissionFlags,
|
||||||
pub envi_flags: EnvironmentFlags,
|
pub envi_flags: EnvironmentFlags,
|
||||||
pub entr_flags: EntryFlags,
|
pub entr_flags: EntryFlags,
|
||||||
pub level_name: String,
|
pub level_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Static environment flags.
|
/// Static environment flags.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct EnvironmentFlags: u16 {
|
pub struct EnvironmentFlags: u16 {
|
||||||
VACUUM = 0,
|
VACUUM = 0,
|
||||||
MAGNETIC = 1,
|
MAGNETIC = 1,
|
||||||
REBELLION = 2,
|
REBELLION = 2,
|
||||||
LOW_GRAV = 3,
|
LOW_GRAV = 3,
|
||||||
M1_GLUE = 4,
|
M1_GLUE = 4,
|
||||||
LAVA_FLOOR = 5,
|
LAVA_FLOOR = 5,
|
||||||
REBELLION2 = 6,
|
REBELLION2 = 6,
|
||||||
MUSIC = 7,
|
MUSIC = 7,
|
||||||
TERM_PAUSE = 8,
|
TERM_PAUSE = 8,
|
||||||
M1_MONSTER = 9,
|
M1_MONSTER = 9,
|
||||||
M1_WEPS = 10,
|
M1_WEPS = 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Static entry point flags.
|
/// Static entry point flags.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct EntryFlags: u32 {
|
pub struct EntryFlags: u32 {
|
||||||
SOLO = 0,
|
SOLO = 0,
|
||||||
CO_OP = 1,
|
CO_OP = 1,
|
||||||
CARNAGE = 2,
|
CARNAGE = 2,
|
||||||
KTMWTB = 3,
|
KTMWTB = 3,
|
||||||
KOTH = 4,
|
KOTH = 4,
|
||||||
DEFENSE = 5,
|
DEFENSE = 5,
|
||||||
RUGBY = 6,
|
RUGBY = 6,
|
||||||
CTF = 7,
|
CTF = 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Static mission flags.
|
/// Static mission flags.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct MissionFlags: u16 {
|
pub struct MissionFlags: u16 {
|
||||||
EXTERMINATION = 0,
|
EXTERMINATION = 0,
|
||||||
EXPLORATION = 1,
|
EXPLORATION = 1,
|
||||||
RETRIEVAL = 2,
|
RETRIEVAL = 2,
|
||||||
REPAIR = 3,
|
REPAIR = 3,
|
||||||
RESCUE = 4,
|
RESCUE = 4,
|
||||||
M1_EXPLORATION = 5,
|
M1_EXPLORATION = 5,
|
||||||
M1_RESCUE = 6,
|
M1_RESCUE = 6,
|
||||||
M1_REPAIR = 7,
|
M1_REPAIR = 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,194 +7,194 @@ use super::{attk, damg};
|
||||||
/// Reads a `MNpx` chunk.
|
/// Reads a `MNpx` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Monster, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Monster, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 156, start: 0, data {
|
endian: BIG, buf: b, size: 156, start: 0, data {
|
||||||
let collection = u16[0];
|
let collection = u16[0];
|
||||||
let vitality = u16[2];
|
let vitality = u16[2];
|
||||||
let dty_immune = u32[4] flag damg::DamageTypeFlags;
|
let dty_immune = u32[4] flag damg::DamageTypeFlags;
|
||||||
let dty_weak = u32[8] flag damg::DamageTypeFlags;
|
let dty_weak = u32[8] flag damg::DamageTypeFlags;
|
||||||
let flags = u32[12] flag MonsterFlags;
|
let flags = u32[12] flag MonsterFlags;
|
||||||
let cls_self = u32[16] flag MonsterClass;
|
let cls_self = u32[16] flag MonsterClass;
|
||||||
let cls_friend = u32[20];
|
let cls_friend = u32[20];
|
||||||
let cls_enemy = u32[24];
|
let cls_enemy = u32[24];
|
||||||
let snd_pitch = Fixed[28];
|
let snd_pitch = Fixed[28];
|
||||||
let snd_see_enemy = OptU16[32];
|
let snd_see_enemy = OptU16[32];
|
||||||
let snd_see_friend = OptU16[34];
|
let snd_see_friend = OptU16[34];
|
||||||
let snd_seeclear = OptU16[36];
|
let snd_seeclear = OptU16[36];
|
||||||
let snd_kill = OptU16[38];
|
let snd_kill = OptU16[38];
|
||||||
let snd_apologize = OptU16[40];
|
let snd_apologize = OptU16[40];
|
||||||
let snd_amicide = OptU16[42];
|
let snd_amicide = OptU16[42];
|
||||||
let snd_flaming = OptU16[44];
|
let snd_flaming = OptU16[44];
|
||||||
let snd_active = OptU16[46];
|
let snd_active = OptU16[46];
|
||||||
let snd_active_mask = u16[48];
|
let snd_active_mask = u16[48];
|
||||||
let typ_item = OptU16[50];
|
let typ_item = OptU16[50];
|
||||||
let radius = Unit[52];
|
let radius = Unit[52];
|
||||||
let height = Unit[54];
|
let height = Unit[54];
|
||||||
let height_hover = Unit[56];
|
let height_hover = Unit[56];
|
||||||
let ledge_min = Unit[58];
|
let ledge_min = Unit[58];
|
||||||
let ledge_max = Unit[60];
|
let ledge_max = Unit[60];
|
||||||
let ext_vel_scale = Fixed[62];
|
let ext_vel_scale = Fixed[62];
|
||||||
let fxt_impact = OptU16[66];
|
let fxt_impact = OptU16[66];
|
||||||
let fxt_impact_melee = OptU16[68];
|
let fxt_impact_melee = OptU16[68];
|
||||||
let fxt_trail = OptU16[70];
|
let fxt_trail = OptU16[70];
|
||||||
let half_fov_horz = u16[72];
|
let half_fov_horz = u16[72];
|
||||||
let half_fov_vert = u16[74];
|
let half_fov_vert = u16[74];
|
||||||
let view_range = Unit[76];
|
let view_range = Unit[76];
|
||||||
let view_range_dark = Unit[78];
|
let view_range_dark = Unit[78];
|
||||||
let intelligence = u16[80];
|
let intelligence = u16[80];
|
||||||
let speed = u16[82];
|
let speed = u16[82];
|
||||||
let gravity = u16[84];
|
let gravity = u16[84];
|
||||||
let vel_terminal = u16[86];
|
let vel_terminal = u16[86];
|
||||||
let door_try_mask = u16[88];
|
let door_try_mask = u16[88];
|
||||||
let expl_radius = OptU16[90];
|
let expl_radius = OptU16[90];
|
||||||
let expl_damage = damg::read[92; 12];
|
let expl_damage = damg::read[92; 12];
|
||||||
let seq_hit = OptU16[104];
|
let seq_hit = OptU16[104];
|
||||||
let seq_dying_hard = OptU16[106];
|
let seq_dying_hard = OptU16[106];
|
||||||
let seq_dying_soft = OptU16[108];
|
let seq_dying_soft = OptU16[108];
|
||||||
let seq_dead_hard = OptU16[110];
|
let seq_dead_hard = OptU16[110];
|
||||||
let seq_dead_soft = OptU16[112];
|
let seq_dead_soft = OptU16[112];
|
||||||
let seq_standing = u16[114];
|
let seq_standing = u16[114];
|
||||||
let seq_moving = u16[116];
|
let seq_moving = u16[116];
|
||||||
let seq_tele_in = OptU16[118];
|
let seq_tele_in = OptU16[118];
|
||||||
let seq_tele_out = OptU16[120];
|
let seq_tele_out = OptU16[120];
|
||||||
let atk_frequency = u16[122];
|
let atk_frequency = u16[122];
|
||||||
let atk_melee = attk::read[124; 16];
|
let atk_melee = attk::read[124; 16];
|
||||||
let atk_range = attk::read[140; 16];
|
let atk_range = attk::read[140; 16];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// friend and enemy fields MUST truncate because the original source code
|
// friend and enemy fields MUST truncate because the original source code
|
||||||
// used `-1` to represent "all classes" which should be invalid normally
|
// used `-1` to represent "all classes" which should be invalid normally
|
||||||
|
|
||||||
let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
|
let cls_friend = MonsterClass::from_bits_truncate(cls_friend);
|
||||||
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
|
let cls_enemy = MonsterClass::from_bits_truncate(cls_enemy);
|
||||||
|
|
||||||
Ok((Monster{collection, vitality, dty_immune, dty_weak, flags, cls_self,
|
Ok((Monster{collection, vitality, dty_immune, dty_weak, flags, cls_self,
|
||||||
cls_friend, cls_enemy, snd_pitch, snd_see_enemy, snd_see_friend,
|
cls_friend, cls_enemy, snd_pitch, snd_see_enemy, snd_see_friend,
|
||||||
snd_seeclear, snd_kill, snd_apologize, snd_amicide, snd_flaming,
|
snd_seeclear, snd_kill, snd_apologize, snd_amicide, snd_flaming,
|
||||||
snd_active, snd_active_mask, typ_item, radius, height,
|
snd_active, snd_active_mask, typ_item, radius, height,
|
||||||
height_hover, ledge_min, ledge_max, ext_vel_scale, fxt_impact,
|
height_hover, ledge_min, ledge_max, ext_vel_scale, fxt_impact,
|
||||||
fxt_impact_melee, fxt_trail, half_fov_horz, half_fov_vert,
|
fxt_impact_melee, fxt_trail, half_fov_horz, half_fov_vert,
|
||||||
view_range, view_range_dark, intelligence, speed, gravity,
|
view_range, view_range_dark, intelligence, speed, gravity,
|
||||||
vel_terminal, door_try_mask, expl_radius, expl_damage, seq_hit,
|
vel_terminal, door_try_mask, expl_radius, expl_damage, seq_hit,
|
||||||
seq_dying_hard, seq_dying_soft, seq_dead_hard, seq_dead_soft,
|
seq_dying_hard, seq_dying_soft, seq_dead_hard, seq_dead_soft,
|
||||||
seq_standing, seq_moving, seq_tele_in, seq_tele_out,
|
seq_standing, seq_moving, seq_tele_in, seq_tele_out,
|
||||||
atk_frequency, atk_melee, atk_range}, 156))
|
atk_frequency, atk_melee, atk_range}, 156))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A monster definition.
|
/// A monster definition.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Monster {
|
pub struct Monster {
|
||||||
pub collection: u16,
|
pub collection: u16,
|
||||||
pub vitality: u16,
|
pub vitality: u16,
|
||||||
pub dty_immune: damg::DamageTypeFlags,
|
pub dty_immune: damg::DamageTypeFlags,
|
||||||
pub dty_weak: damg::DamageTypeFlags,
|
pub dty_weak: damg::DamageTypeFlags,
|
||||||
pub flags: MonsterFlags,
|
pub flags: MonsterFlags,
|
||||||
pub cls_self: MonsterClass,
|
pub cls_self: MonsterClass,
|
||||||
pub cls_friend: MonsterClass,
|
pub cls_friend: MonsterClass,
|
||||||
pub cls_enemy: MonsterClass,
|
pub cls_enemy: MonsterClass,
|
||||||
pub snd_pitch: Fixed,
|
pub snd_pitch: Fixed,
|
||||||
pub snd_see_enemy: OptU16,
|
pub snd_see_enemy: OptU16,
|
||||||
pub snd_see_friend: OptU16,
|
pub snd_see_friend: OptU16,
|
||||||
pub snd_seeclear: OptU16,
|
pub snd_seeclear: OptU16,
|
||||||
pub snd_kill: OptU16,
|
pub snd_kill: OptU16,
|
||||||
pub snd_apologize: OptU16,
|
pub snd_apologize: OptU16,
|
||||||
pub snd_amicide: OptU16,
|
pub snd_amicide: OptU16,
|
||||||
pub snd_flaming: OptU16,
|
pub snd_flaming: OptU16,
|
||||||
pub snd_active: OptU16,
|
pub snd_active: OptU16,
|
||||||
pub snd_active_mask: u16,
|
pub snd_active_mask: u16,
|
||||||
pub typ_item: OptU16,
|
pub typ_item: OptU16,
|
||||||
pub radius: Unit,
|
pub radius: Unit,
|
||||||
pub height: Unit,
|
pub height: Unit,
|
||||||
pub height_hover: Unit,
|
pub height_hover: Unit,
|
||||||
pub ledge_min: Unit,
|
pub ledge_min: Unit,
|
||||||
pub ledge_max: Unit,
|
pub ledge_max: Unit,
|
||||||
pub ext_vel_scale: Fixed,
|
pub ext_vel_scale: Fixed,
|
||||||
pub fxt_impact: OptU16,
|
pub fxt_impact: OptU16,
|
||||||
pub fxt_impact_melee: OptU16,
|
pub fxt_impact_melee: OptU16,
|
||||||
pub fxt_trail: OptU16,
|
pub fxt_trail: OptU16,
|
||||||
pub half_fov_horz: u16,
|
pub half_fov_horz: u16,
|
||||||
pub half_fov_vert: u16,
|
pub half_fov_vert: u16,
|
||||||
pub view_range: Unit,
|
pub view_range: Unit,
|
||||||
pub view_range_dark: Unit,
|
pub view_range_dark: Unit,
|
||||||
pub intelligence: u16,
|
pub intelligence: u16,
|
||||||
pub speed: u16,
|
pub speed: u16,
|
||||||
pub gravity: u16,
|
pub gravity: u16,
|
||||||
pub vel_terminal: u16,
|
pub vel_terminal: u16,
|
||||||
pub door_try_mask: u16,
|
pub door_try_mask: u16,
|
||||||
pub expl_radius: OptU16,
|
pub expl_radius: OptU16,
|
||||||
pub expl_damage: damg::Damage,
|
pub expl_damage: damg::Damage,
|
||||||
pub seq_hit: OptU16,
|
pub seq_hit: OptU16,
|
||||||
pub seq_dying_hard: OptU16,
|
pub seq_dying_hard: OptU16,
|
||||||
pub seq_dying_soft: OptU16,
|
pub seq_dying_soft: OptU16,
|
||||||
pub seq_dead_hard: OptU16,
|
pub seq_dead_hard: OptU16,
|
||||||
pub seq_dead_soft: OptU16,
|
pub seq_dead_soft: OptU16,
|
||||||
pub seq_standing: u16,
|
pub seq_standing: u16,
|
||||||
pub seq_moving: u16,
|
pub seq_moving: u16,
|
||||||
pub seq_tele_in: OptU16,
|
pub seq_tele_in: OptU16,
|
||||||
pub seq_tele_out: OptU16,
|
pub seq_tele_out: OptU16,
|
||||||
pub atk_frequency: u16,
|
pub atk_frequency: u16,
|
||||||
pub atk_melee: attk::Attack,
|
pub atk_melee: attk::Attack,
|
||||||
pub atk_range: attk::Attack,
|
pub atk_range: attk::Attack,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for a monster.
|
/// Flags for a monster.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct MonsterFlags: u32 {
|
pub struct MonsterFlags: u32 {
|
||||||
IGNORE_LOS = 0,
|
IGNORE_LOS = 0,
|
||||||
FLYING = 1,
|
FLYING = 1,
|
||||||
ALIEN = 2,
|
ALIEN = 2,
|
||||||
MAJOR = 3,
|
MAJOR = 3,
|
||||||
MINOR = 4,
|
MINOR = 4,
|
||||||
NO_OMIT = 5,
|
NO_OMIT = 5,
|
||||||
FLOATS = 6,
|
FLOATS = 6,
|
||||||
NO_ATTACK = 7,
|
NO_ATTACK = 7,
|
||||||
SNIPE = 8,
|
SNIPE = 8,
|
||||||
INVISIBLE = 9,
|
INVISIBLE = 9,
|
||||||
SUBTLY_INVISIBLE = 10,
|
SUBTLY_INVISIBLE = 10,
|
||||||
KAMIKAZE = 11,
|
KAMIKAZE = 11,
|
||||||
BERSERKER = 12,
|
BERSERKER = 12,
|
||||||
ENLARGED = 13,
|
ENLARGED = 13,
|
||||||
DELAYED_DEATH = 14,
|
DELAYED_DEATH = 14,
|
||||||
FIRE_SYMMETRICAL = 15,
|
FIRE_SYMMETRICAL = 15,
|
||||||
NUCLEAR_DEATH = 16,
|
NUCLEAR_DEATH = 16,
|
||||||
NO_FIRE_BACKWARDS = 17,
|
NO_FIRE_BACKWARDS = 17,
|
||||||
CAN_DIE_IN_FLAMES = 18,
|
CAN_DIE_IN_FLAMES = 18,
|
||||||
WAIT_FOR_GOOD_SHOT = 19,
|
WAIT_FOR_GOOD_SHOT = 19,
|
||||||
TINY = 20,
|
TINY = 20,
|
||||||
FAST_ATTACK = 21,
|
FAST_ATTACK = 21,
|
||||||
LIKES_WATER = 22,
|
LIKES_WATER = 22,
|
||||||
LIKES_SEWAGE = 23,
|
LIKES_SEWAGE = 23,
|
||||||
LIKES_LAVA = 24,
|
LIKES_LAVA = 24,
|
||||||
LIKES_GOO = 25,
|
LIKES_GOO = 25,
|
||||||
TELE_UNDER_MEDIA = 26,
|
TELE_UNDER_MEDIA = 26,
|
||||||
USE_RANDOM_WEAPON = 27,
|
USE_RANDOM_WEAPON = 27,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// The composite type of a monster.
|
/// The composite type of a monster.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct MonsterClass: u32 {
|
pub struct MonsterClass: u32 {
|
||||||
PLAYER = 0,
|
PLAYER = 0,
|
||||||
CIVILIAN = 1,
|
CIVILIAN = 1,
|
||||||
MADD = 2,
|
MADD = 2,
|
||||||
POSSESSED_HUMMER = 3,
|
POSSESSED_HUMMER = 3,
|
||||||
DEFENDER = 4,
|
DEFENDER = 4,
|
||||||
FIGHTER = 5,
|
FIGHTER = 5,
|
||||||
TROOPER = 6,
|
TROOPER = 6,
|
||||||
HUNTER = 7,
|
HUNTER = 7,
|
||||||
ENFORCER = 8,
|
ENFORCER = 8,
|
||||||
JUGGERNAUT = 9,
|
JUGGERNAUT = 9,
|
||||||
HUMMER = 10,
|
HUMMER = 10,
|
||||||
COMPILER = 11,
|
COMPILER = 11,
|
||||||
CYBORG = 12,
|
CYBORG = 12,
|
||||||
ASSIMILATED = 13,
|
ASSIMILATED = 13,
|
||||||
TICK = 14,
|
TICK = 14,
|
||||||
YETI = 15,
|
YETI = 15,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{err::*, text::mac_roman_cstr};
|
||||||
/// Reads a `NAME` chunk.
|
/// Reads a `NAME` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(String, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(String, usize)>
|
||||||
{
|
{
|
||||||
Ok((mac_roman_cstr(b), b.len()))
|
Ok((mac_roman_cstr(b), b.len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,24 +6,24 @@ use crate::{err::*, text::*};
|
||||||
/// Reads a `NOTE` chunk.
|
/// Reads a `NOTE` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Note, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Note, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 72, start: 0, data {
|
endian: BIG, buf: b, size: 72, start: 0, data {
|
||||||
let pos = pnts::read_o[2; 4];
|
let pos = pnts::read_o[2; 4];
|
||||||
let poly = u16[6];
|
let poly = u16[6];
|
||||||
let text = mac_roman_cstr[8; 64] no_try;
|
let text = mac_roman_cstr[8; 64] no_try;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Note{pos, poly, text}, 72))
|
Ok((Note{pos, poly, text}, 72))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Overhead map annotations.
|
/// Overhead map annotations.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Note {
|
pub struct Note {
|
||||||
pub pos: pnts::Point,
|
pub pos: pnts::Point,
|
||||||
pub poly: u16,
|
pub poly: u16,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,53 +5,53 @@ use crate::{err::*, fixed::{Angle, Unit}};
|
||||||
/// Reads an `OBJS` chunk.
|
/// Reads an `OBJS` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Object, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Object, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 16, start: 0, data {
|
endian: BIG, buf: b, size: 16, start: 0, data {
|
||||||
let group = u16[0];
|
let group = u16[0];
|
||||||
let index = u16[2];
|
let index = u16[2];
|
||||||
let angle = Angle[4];
|
let angle = Angle[4];
|
||||||
let poly = u16[6];
|
let poly = u16[6];
|
||||||
let pos_x = Unit[8];
|
let pos_x = Unit[8];
|
||||||
let pos_y = Unit[10];
|
let pos_y = Unit[10];
|
||||||
let pos_z = Unit[12];
|
let pos_z = Unit[12];
|
||||||
let flags = u16[14];
|
let flags = u16[14];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let bias = flags & 0xF0_00;
|
let bias = flags & 0xF0_00;
|
||||||
let flags = flags & 0x0F_FF;
|
let flags = flags & 0x0F_FF;
|
||||||
let bias = bias >> 12;
|
let bias = bias >> 12;
|
||||||
let flags = flag_ok!(ObjectFlags, flags)?;
|
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.
|
/// An object in the world.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Object {
|
pub struct Object {
|
||||||
pub group: u16,
|
pub group: u16,
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
pub angle: Angle,
|
pub angle: Angle,
|
||||||
pub poly: u16,
|
pub poly: u16,
|
||||||
pub pos_x: Unit,
|
pub pos_x: Unit,
|
||||||
pub pos_y: Unit,
|
pub pos_y: Unit,
|
||||||
pub pos_z: Unit,
|
pub pos_z: Unit,
|
||||||
pub flags: ObjectFlags,
|
pub flags: ObjectFlags,
|
||||||
pub bias: u16,
|
pub bias: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Object`.
|
/// Flags for `Object`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct ObjectFlags: u16 {
|
pub struct ObjectFlags: u16 {
|
||||||
INVISIBLE = 0,
|
INVISIBLE = 0,
|
||||||
CEILING = 1,
|
CEILING = 1,
|
||||||
BLIND = 2,
|
BLIND = 2,
|
||||||
DEAF = 3,
|
DEAF = 3,
|
||||||
FLOATING = 4,
|
FLOATING = 4,
|
||||||
NET_ONLY = 5,
|
NET_ONLY = 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,42 +5,42 @@ use crate::err::*;
|
||||||
/// Reads a `plac` chunk.
|
/// Reads a `plac` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(ObjectFreq, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 12, start: 0, data {
|
endian: BIG, buf: b, size: 12, start: 0, data {
|
||||||
let flags = u16[0] flag ObjectFreqFlags;
|
let flags = u16[0] flag ObjectFreqFlags;
|
||||||
let cnt_ini = u16[2];
|
let cnt_ini = u16[2];
|
||||||
let cnt_min = u16[4];
|
let cnt_min = u16[4];
|
||||||
let cnt_max = u16[6];
|
let cnt_max = u16[6];
|
||||||
let cnt_rnd = u16[8];
|
let cnt_rnd = u16[8];
|
||||||
let chance = u16[10];
|
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.
|
/// The difficulty definition for various object types.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct ObjectFreq {
|
pub struct ObjectFreq {
|
||||||
pub flags: ObjectFreqFlags,
|
pub flags: ObjectFreqFlags,
|
||||||
pub cnt_ini: u16,
|
pub cnt_ini: u16,
|
||||||
pub cnt_min: u16,
|
pub cnt_min: u16,
|
||||||
pub cnt_max: u16,
|
pub cnt_max: u16,
|
||||||
pub cnt_rnd: u16,
|
pub cnt_rnd: u16,
|
||||||
pub chance: u16,
|
pub chance: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `ObjectFreq`.
|
/// Flags for `ObjectFreq`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct ObjectFreqFlags: u16 {
|
pub struct ObjectFreqFlags: u16 {
|
||||||
RANDOM_LOCATION = 0,
|
RANDOM_LOCATION = 0,
|
||||||
_3 = 3,
|
_3 = 3,
|
||||||
_4 = 4,
|
_4 = 4,
|
||||||
_5 = 5,
|
_5 = 5,
|
||||||
_6 = 6,
|
_6 = 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,68 +5,68 @@ use crate::{err::*, fixed::Unit};
|
||||||
/// Reads a `plat` chunk.
|
/// Reads a `plat` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Platform, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Platform, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 32, start: 0, data {
|
endian: BIG, buf: b, size: 32, start: 0, data {
|
||||||
let ptype = u16[0];
|
let ptype = u16[0];
|
||||||
let speed = u16[2];
|
let speed = u16[2];
|
||||||
let delay = u16[4];
|
let delay = u16[4];
|
||||||
let hei_max = Unit[6];
|
let hei_max = Unit[6];
|
||||||
let hei_min = Unit[8];
|
let hei_min = Unit[8];
|
||||||
let flags = u32[10] flag PlatformFlags;
|
let flags = u32[10] flag PlatformFlags;
|
||||||
let index = u16[14];
|
let index = u16[14];
|
||||||
let tag = u16[16];
|
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.
|
/// Extra information for polygons with platforms.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Platform {
|
pub struct Platform {
|
||||||
pub ptype: u16,
|
pub ptype: u16,
|
||||||
pub speed: u16,
|
pub speed: u16,
|
||||||
pub delay: u16,
|
pub delay: u16,
|
||||||
pub hei_min: Unit,
|
pub hei_min: Unit,
|
||||||
pub hei_max: Unit,
|
pub hei_max: Unit,
|
||||||
pub flags: PlatformFlags,
|
pub flags: PlatformFlags,
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
pub tag: u16,
|
pub tag: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Platform`.
|
/// Flags for `Platform`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct PlatformFlags: u32 {
|
pub struct PlatformFlags: u32 {
|
||||||
INIT_ACTIVE = 0,
|
INIT_ACTIVE = 0,
|
||||||
INIT_EXTENDED = 1,
|
INIT_EXTENDED = 1,
|
||||||
STOP_AT_EACH_LEVEL = 2,
|
STOP_AT_EACH_LEVEL = 2,
|
||||||
STOP_AT_INIT_LEVEL = 3,
|
STOP_AT_INIT_LEVEL = 3,
|
||||||
START_ADJ_ON_STOP = 4,
|
START_ADJ_ON_STOP = 4,
|
||||||
EXTENDS_FLOOR_TO_CEIL = 5,
|
EXTENDS_FLOOR_TO_CEIL = 5,
|
||||||
COMES_FROM_FLOOR = 6,
|
COMES_FROM_FLOOR = 6,
|
||||||
COMES_FROM_CEIL = 7,
|
COMES_FROM_CEIL = 7,
|
||||||
CAUSES_DAMAGE = 8,
|
CAUSES_DAMAGE = 8,
|
||||||
NO_ACTIVATE_PARENT = 9,
|
NO_ACTIVATE_PARENT = 9,
|
||||||
ACTIVATES_ONCE = 10,
|
ACTIVATES_ONCE = 10,
|
||||||
ACTIVATES_LIGHT = 11,
|
ACTIVATES_LIGHT = 11,
|
||||||
DEACTIVATES_LIGHT = 12,
|
DEACTIVATES_LIGHT = 12,
|
||||||
PLAYER_CONTROLS = 13,
|
PLAYER_CONTROLS = 13,
|
||||||
MONSTER_CONTROLS = 14,
|
MONSTER_CONTROLS = 14,
|
||||||
REVERSE_ON_OBSTRUCT = 15,
|
REVERSE_ON_OBSTRUCT = 15,
|
||||||
NO_EXT_DEACTIVATION = 16,
|
NO_EXT_DEACTIVATION = 16,
|
||||||
USE_POLYGON_HEIGHTS = 17,
|
USE_POLYGON_HEIGHTS = 17,
|
||||||
DELAYED_ACTIVATION = 18,
|
DELAYED_ACTIVATION = 18,
|
||||||
START_ADJ_ON_START = 19,
|
START_ADJ_ON_START = 19,
|
||||||
STOP_ADJ_ON_START = 20,
|
STOP_ADJ_ON_START = 20,
|
||||||
STOP_ADJ_ON_STOP = 21,
|
STOP_ADJ_ON_STOP = 21,
|
||||||
SLOW = 22,
|
SLOW = 22,
|
||||||
START_AT_EACH_LEVEL = 23,
|
START_AT_EACH_LEVEL = 23,
|
||||||
LOCKED = 24,
|
LOCKED = 24,
|
||||||
SECRET = 25,
|
SECRET = 25,
|
||||||
DOOR = 26,
|
DOOR = 26,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,23 +5,23 @@ use crate::{err::*, fixed::Unit};
|
||||||
/// Reads a `Point` object.
|
/// Reads a `Point` object.
|
||||||
pub fn read_o(b: &[u8]) -> ResultS<Point>
|
pub fn read_o(b: &[u8]) -> ResultS<Point>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 4, start: 0, data {
|
endian: BIG, buf: b, size: 4, start: 0, data {
|
||||||
let x = Unit[0];
|
let x = Unit[0];
|
||||||
let y = Unit[2];
|
let y = Unit[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Point{x, y})
|
Ok(Point{x, y})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a `Point` object.
|
/// Writes a `Point` object.
|
||||||
pub fn write_o(v: Point) -> Vec<u8>
|
pub fn write_o(v: Point) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut o = Vec::with_capacity(4);
|
let mut o = Vec::with_capacity(4);
|
||||||
o.extend(&v.x.to_be_bytes());
|
o.extend(&v.x.to_be_bytes());
|
||||||
o.extend(&v.y.to_be_bytes());
|
o.extend(&v.y.to_be_bytes());
|
||||||
o
|
o
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a `PNTS` chunk.
|
/// 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))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
pub x: Unit,
|
pub x: Unit,
|
||||||
pub y: Unit,
|
pub y: Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,185 +6,185 @@ use crate::{bin::OptU16, err::*, fixed::Unit, xfer::TransferMode};
|
||||||
/// Reads a polygon for either M1 or M2.
|
/// Reads a polygon for either M1 or M2.
|
||||||
pub fn read_poly_inter(b: &[u8]) -> ResultS<Polygon>
|
pub fn read_poly_inter(b: &[u8]) -> ResultS<Polygon>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 128, start: 0, data {
|
endian: BIG, buf: b, size: 128, start: 0, data {
|
||||||
let tex_flr = OptU16[40];
|
let tex_flr = OptU16[40];
|
||||||
let tex_cei = OptU16[42];
|
let tex_cei = OptU16[42];
|
||||||
let hei_flr = Unit[44];
|
let hei_flr = Unit[44];
|
||||||
let hei_cei = Unit[46];
|
let hei_cei = Unit[46];
|
||||||
let lit_flr = u16[48];
|
let lit_flr = u16[48];
|
||||||
let lit_cei = u16[50];
|
let lit_cei = u16[50];
|
||||||
let xfr_flr = u16[64] enum TransferMode;
|
let xfr_flr = u16[64] enum TransferMode;
|
||||||
let xfr_cei = u16[66] 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,
|
Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr,
|
||||||
xfr_cei, ..Polygon::default()})
|
xfr_cei, ..Polygon::default()})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a `POLY` chunk.
|
/// Reads a `POLY` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Polygon, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Polygon, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 128, start: 0, data {
|
endian: BIG, buf: b, size: 128, start: 0, data {
|
||||||
let ptype = u16[0];
|
let ptype = u16[0];
|
||||||
let pdata = u16[4];
|
let pdata = u16[4];
|
||||||
let ori_flr = pnts::read_o[108; 4];
|
let ori_flr = pnts::read_o[108; 4];
|
||||||
let ori_cei = pnts::read_o[112; 4];
|
let ori_cei = pnts::read_o[112; 4];
|
||||||
let med_ind = OptU16[116];
|
let med_ind = OptU16[116];
|
||||||
let med_ctl = u16[118];
|
let med_ctl = u16[118];
|
||||||
let snd_amb = OptU16[122];
|
let snd_amb = OptU16[122];
|
||||||
let snd_ind = u16[120];
|
let snd_ind = u16[120];
|
||||||
let snd_rnd = OptU16[124];
|
let snd_rnd = OptU16[124];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let poly = read_poly_inter(b)?;
|
let poly = read_poly_inter(b)?;
|
||||||
let ptype = PolygonType::new(ptype, pdata)?;
|
let ptype = PolygonType::new(ptype, pdata)?;
|
||||||
|
|
||||||
Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb,
|
Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb,
|
||||||
snd_rnd, ..poly}, 128))
|
snd_rnd, ..poly}, 128))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an old `POLY` chunk.
|
/// Reads an old `POLY` chunk.
|
||||||
pub fn read_old(b: &[u8]) -> ResultS<(Polygon, usize)>
|
pub fn read_old(b: &[u8]) -> ResultS<(Polygon, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 128, start: 0, data {
|
endian: BIG, buf: b, size: 128, start: 0, data {
|
||||||
let ptype = u16[0];
|
let ptype = u16[0];
|
||||||
let pdata = u16[4];
|
let pdata = u16[4];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let poly = read_poly_inter(b)?;
|
let poly = read_poly_inter(b)?;
|
||||||
let ptype = PolygonType::new_old(ptype, pdata)?;
|
let ptype = PolygonType::new_old(ptype, pdata)?;
|
||||||
|
|
||||||
Ok((Polygon{ptype, ..poly}, 128))
|
Ok((Polygon{ptype, ..poly}, 128))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PolygonType
|
impl PolygonType
|
||||||
{
|
{
|
||||||
/// Creates a `PolygonType` from a `n`/`pdata` pair.
|
/// Creates a `PolygonType` from a `n`/`pdata` pair.
|
||||||
pub fn new(n: u16, pdata: u16) -> Result<Self, ReprError>
|
pub fn new(n: u16, pdata: u16) -> Result<Self, ReprError>
|
||||||
{
|
{
|
||||||
match n {
|
match n {
|
||||||
0 => Ok(PolygonType::Normal),
|
0 => Ok(PolygonType::Normal),
|
||||||
1 => Ok(PolygonType::ImpassItem),
|
1 => Ok(PolygonType::ImpassItem),
|
||||||
2 => Ok(PolygonType::ImpassMons),
|
2 => Ok(PolygonType::ImpassMons),
|
||||||
3 => Ok(PolygonType::Hill),
|
3 => Ok(PolygonType::Hill),
|
||||||
4 => Ok(PolygonType::Base),
|
4 => Ok(PolygonType::Base),
|
||||||
5 => Ok(PolygonType::Platform(pdata)),
|
5 => Ok(PolygonType::Platform(pdata)),
|
||||||
6 => Ok(PolygonType::TrigLightOn(pdata)),
|
6 => Ok(PolygonType::TrigLightOn(pdata)),
|
||||||
7 => Ok(PolygonType::TrigPlatOn(pdata)),
|
7 => Ok(PolygonType::TrigPlatOn(pdata)),
|
||||||
8 => Ok(PolygonType::TrigLightOff(pdata)),
|
8 => Ok(PolygonType::TrigLightOff(pdata)),
|
||||||
9 => Ok(PolygonType::TrigPlatOff(pdata)),
|
9 => Ok(PolygonType::TrigPlatOff(pdata)),
|
||||||
10 => Ok(PolygonType::Teleporter(pdata)),
|
10 => Ok(PolygonType::Teleporter(pdata)),
|
||||||
11 => Ok(PolygonType::ZoneBorder),
|
11 => Ok(PolygonType::ZoneBorder),
|
||||||
12 => Ok(PolygonType::Goal),
|
12 => Ok(PolygonType::Goal),
|
||||||
13 => Ok(PolygonType::TrigMonsVis),
|
13 => Ok(PolygonType::TrigMonsVis),
|
||||||
14 => Ok(PolygonType::TrigMonsInv),
|
14 => Ok(PolygonType::TrigMonsInv),
|
||||||
15 => Ok(PolygonType::TrigMonsDual),
|
15 => Ok(PolygonType::TrigMonsDual),
|
||||||
16 => Ok(PolygonType::TrigItems),
|
16 => Ok(PolygonType::TrigItems),
|
||||||
17 => Ok(PolygonType::MustExplore),
|
17 => Ok(PolygonType::MustExplore),
|
||||||
18 => Ok(PolygonType::AutoExit),
|
18 => Ok(PolygonType::AutoExit),
|
||||||
19 => Ok(PolygonType::OuchMinor),
|
19 => Ok(PolygonType::OuchMinor),
|
||||||
20 => Ok(PolygonType::OuchMajor),
|
20 => Ok(PolygonType::OuchMajor),
|
||||||
21 => Ok(PolygonType::Glue),
|
21 => Ok(PolygonType::Glue),
|
||||||
22 => Ok(PolygonType::GlueTrigger(pdata)),
|
22 => Ok(PolygonType::GlueTrigger(pdata)),
|
||||||
23 => Ok(PolygonType::GlueSuper),
|
23 => Ok(PolygonType::GlueSuper),
|
||||||
n => Err(ReprError::new("PolygonType", n)),
|
n => Err(ReprError::new("PolygonType", n)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `PolygonType` from a Marathon 1 compatible `n`/`pdata` pair.
|
/// Creates a `PolygonType` from a Marathon 1 compatible `n`/`pdata` pair.
|
||||||
fn new_old(n: u16, pdata: u16) -> Result<Self, ReprError>
|
fn new_old(n: u16, pdata: u16) -> Result<Self, ReprError>
|
||||||
{
|
{
|
||||||
match n {
|
match n {
|
||||||
0 => Ok(PolygonType::Normal),
|
0 => Ok(PolygonType::Normal),
|
||||||
1 => Ok(PolygonType::ImpassItem),
|
1 => Ok(PolygonType::ImpassItem),
|
||||||
2 => Ok(PolygonType::ImpassMons),
|
2 => Ok(PolygonType::ImpassMons),
|
||||||
3 => Ok(PolygonType::OuchMinor),
|
3 => Ok(PolygonType::OuchMinor),
|
||||||
4 => Ok(PolygonType::OuchMajor),
|
4 => Ok(PolygonType::OuchMajor),
|
||||||
5 => Ok(PolygonType::Platform(pdata)),
|
5 => Ok(PolygonType::Platform(pdata)),
|
||||||
6 => Ok(PolygonType::TrigLightOn(pdata)),
|
6 => Ok(PolygonType::TrigLightOn(pdata)),
|
||||||
7 => Ok(PolygonType::TrigPlatOn(pdata)),
|
7 => Ok(PolygonType::TrigPlatOn(pdata)),
|
||||||
8 => Ok(PolygonType::TrigLightOff(pdata)),
|
8 => Ok(PolygonType::TrigLightOff(pdata)),
|
||||||
9 => Ok(PolygonType::TrigPlatOff(pdata)),
|
9 => Ok(PolygonType::TrigPlatOff(pdata)),
|
||||||
10 => Ok(PolygonType::Teleporter(pdata)),
|
10 => Ok(PolygonType::Teleporter(pdata)),
|
||||||
11 => Ok(PolygonType::Glue),
|
11 => Ok(PolygonType::Glue),
|
||||||
12 => Ok(PolygonType::GlueTrigger(pdata)),
|
12 => Ok(PolygonType::GlueTrigger(pdata)),
|
||||||
13 => Ok(PolygonType::GlueSuper),
|
13 => Ok(PolygonType::GlueSuper),
|
||||||
14 => Ok(PolygonType::MustExplore),
|
14 => Ok(PolygonType::MustExplore),
|
||||||
15 => Ok(PolygonType::AutoExit),
|
15 => Ok(PolygonType::AutoExit),
|
||||||
n => Err(ReprError::new("PolygonType", n)),
|
n => Err(ReprError::new("PolygonType", n)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PolygonType
|
impl Default for PolygonType
|
||||||
{
|
{
|
||||||
fn default() -> Self {PolygonType::Normal}
|
fn default() -> Self {PolygonType::Normal}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A polygon segment.
|
/// A polygon segment.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct Polygon {
|
pub struct Polygon {
|
||||||
pub ptype: PolygonType,
|
pub ptype: PolygonType,
|
||||||
pub tex_flr: OptU16,
|
pub tex_flr: OptU16,
|
||||||
pub tex_cei: OptU16,
|
pub tex_cei: OptU16,
|
||||||
pub hei_flr: Unit,
|
pub hei_flr: Unit,
|
||||||
pub hei_cei: Unit,
|
pub hei_cei: Unit,
|
||||||
pub lit_flr: u16,
|
pub lit_flr: u16,
|
||||||
pub lit_cei: u16,
|
pub lit_cei: u16,
|
||||||
pub xfr_flr: TransferMode,
|
pub xfr_flr: TransferMode,
|
||||||
pub xfr_cei: TransferMode,
|
pub xfr_cei: TransferMode,
|
||||||
pub ori_flr: pnts::Point,
|
pub ori_flr: pnts::Point,
|
||||||
pub ori_cei: pnts::Point,
|
pub ori_cei: pnts::Point,
|
||||||
pub med_ind: OptU16,
|
pub med_ind: OptU16,
|
||||||
pub med_ctl: u16,
|
pub med_ctl: u16,
|
||||||
pub snd_ind: u16,
|
pub snd_ind: u16,
|
||||||
pub snd_amb: OptU16,
|
pub snd_amb: OptU16,
|
||||||
pub snd_rnd: OptU16,
|
pub snd_rnd: OptU16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The action type of a `Polygon`.
|
/// The action type of a `Polygon`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum PolygonType {
|
pub enum PolygonType {
|
||||||
Normal,
|
Normal,
|
||||||
ImpassItem,
|
ImpassItem,
|
||||||
ImpassMons,
|
ImpassMons,
|
||||||
Hill,
|
Hill,
|
||||||
Base,
|
Base,
|
||||||
Platform(u16),
|
Platform(u16),
|
||||||
TrigLightOn(u16),
|
TrigLightOn(u16),
|
||||||
TrigPlatOn(u16),
|
TrigPlatOn(u16),
|
||||||
TrigLightOff(u16),
|
TrigLightOff(u16),
|
||||||
TrigPlatOff(u16),
|
TrigPlatOff(u16),
|
||||||
Teleporter(u16),
|
Teleporter(u16),
|
||||||
ZoneBorder,
|
ZoneBorder,
|
||||||
Goal,
|
Goal,
|
||||||
TrigMonsVis,
|
TrigMonsVis,
|
||||||
TrigMonsInv,
|
TrigMonsInv,
|
||||||
TrigMonsDual,
|
TrigMonsDual,
|
||||||
TrigItems,
|
TrigItems,
|
||||||
MustExplore,
|
MustExplore,
|
||||||
AutoExit,
|
AutoExit,
|
||||||
OuchMinor,
|
OuchMinor,
|
||||||
OuchMajor,
|
OuchMajor,
|
||||||
Glue,
|
Glue,
|
||||||
GlueTrigger(u16),
|
GlueTrigger(u16),
|
||||||
GlueSuper,
|
GlueSuper,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Polygon`.
|
/// Flags for `Polygon`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct PolygonFlags: u16 {
|
pub struct PolygonFlags: u16 {
|
||||||
DETACHED = 14,
|
DETACHED = 14,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,83 +7,83 @@ use super::damg;
|
||||||
/// Reads a `PRpx` chunk.
|
/// Reads a `PRpx` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Projectile, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Projectile, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 48, start: 0, data {
|
endian: BIG, buf: b, size: 48, start: 0, data {
|
||||||
let collection = OptU16[0];
|
let collection = OptU16[0];
|
||||||
let shape = u16[2];
|
let shape = u16[2];
|
||||||
let fxt_explode = OptU16[4];
|
let fxt_explode = OptU16[4];
|
||||||
let fxt_exp_media = OptU16[6];
|
let fxt_exp_media = OptU16[6];
|
||||||
let fxt_trail = OptU16[8];
|
let fxt_trail = OptU16[8];
|
||||||
let tic_trail = u16[10];
|
let tic_trail = u16[10];
|
||||||
let max_trail = OptU16[12];
|
let max_trail = OptU16[12];
|
||||||
let typ_media = OptU16[14];
|
let typ_media = OptU16[14];
|
||||||
let radius = Unit[16];
|
let radius = Unit[16];
|
||||||
let dmg_rad = Unit[18];
|
let dmg_rad = Unit[18];
|
||||||
let dmg_def = damg::read[20; 12];
|
let dmg_def = damg::read[20; 12];
|
||||||
let flags = u32[32] flag ProjectileFlags;
|
let flags = u32[32] flag ProjectileFlags;
|
||||||
let speed = Unit[36];
|
let speed = Unit[36];
|
||||||
let range = Unit[38];
|
let range = Unit[38];
|
||||||
let snd_pitch = Fixed[40];
|
let snd_pitch = Fixed[40];
|
||||||
let snd_fly = OptU16[44];
|
let snd_fly = OptU16[44];
|
||||||
let snd_bounce = OptU16[46];
|
let snd_bounce = OptU16[46];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Projectile{collection, shape, fxt_explode, fxt_exp_media, fxt_trail,
|
Ok((Projectile{collection, shape, fxt_explode, fxt_exp_media, fxt_trail,
|
||||||
tic_trail, max_trail, typ_media, radius, dmg_rad, dmg_def,
|
tic_trail, max_trail, typ_media, radius, dmg_rad, dmg_def,
|
||||||
flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48))
|
flags, speed, range, snd_pitch, snd_fly, snd_bounce}, 48))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A projectile definition.
|
/// A projectile definition.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Projectile {
|
pub struct Projectile {
|
||||||
pub collection: OptU16,
|
pub collection: OptU16,
|
||||||
pub shape: u16,
|
pub shape: u16,
|
||||||
pub fxt_explode: OptU16,
|
pub fxt_explode: OptU16,
|
||||||
pub fxt_exp_media: OptU16,
|
pub fxt_exp_media: OptU16,
|
||||||
pub fxt_trail: OptU16,
|
pub fxt_trail: OptU16,
|
||||||
pub tic_trail: u16,
|
pub tic_trail: u16,
|
||||||
pub max_trail: OptU16,
|
pub max_trail: OptU16,
|
||||||
pub typ_media: OptU16,
|
pub typ_media: OptU16,
|
||||||
pub radius: Unit,
|
pub radius: Unit,
|
||||||
pub dmg_rad: Unit,
|
pub dmg_rad: Unit,
|
||||||
pub dmg_def: damg::Damage,
|
pub dmg_def: damg::Damage,
|
||||||
pub flags: ProjectileFlags,
|
pub flags: ProjectileFlags,
|
||||||
pub speed: Unit,
|
pub speed: Unit,
|
||||||
pub range: Unit,
|
pub range: Unit,
|
||||||
pub snd_pitch: Fixed,
|
pub snd_pitch: Fixed,
|
||||||
pub snd_fly: OptU16,
|
pub snd_fly: OptU16,
|
||||||
pub snd_bounce: OptU16,
|
pub snd_bounce: OptU16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for a projectile.
|
/// Flags for a projectile.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct ProjectileFlags: u32 {
|
pub struct ProjectileFlags: u32 {
|
||||||
GUIDED = 0,
|
GUIDED = 0,
|
||||||
STOP_ON_LOOP = 1,
|
STOP_ON_LOOP = 1,
|
||||||
PERSISTENT = 2,
|
PERSISTENT = 2,
|
||||||
ALIEN = 3,
|
ALIEN = 3,
|
||||||
GRAVITY = 4,
|
GRAVITY = 4,
|
||||||
NO_HORZ_ERROR = 5,
|
NO_HORZ_ERROR = 5,
|
||||||
NO_VERT_ERROR = 6,
|
NO_VERT_ERROR = 6,
|
||||||
TOGGLE_PANELS = 7,
|
TOGGLE_PANELS = 7,
|
||||||
POS_VERT_ERROR = 8,
|
POS_VERT_ERROR = 8,
|
||||||
MELEE = 9,
|
MELEE = 9,
|
||||||
RIPPER = 10,
|
RIPPER = 10,
|
||||||
PASS_TRANS_RANDOM = 11,
|
PASS_TRANS_RANDOM = 11,
|
||||||
PASS_TRANS_MORE = 12,
|
PASS_TRANS_MORE = 12,
|
||||||
DOUBLE_GRAVITY = 13,
|
DOUBLE_GRAVITY = 13,
|
||||||
REBOUND_FLOOR = 14,
|
REBOUND_FLOOR = 14,
|
||||||
THROUGH_MEDIA = 15,
|
THROUGH_MEDIA = 15,
|
||||||
BECOME_ITEM = 16,
|
BECOME_ITEM = 16,
|
||||||
BLOODY = 17,
|
BLOODY = 17,
|
||||||
WANDER_HORZ = 18,
|
WANDER_HORZ = 18,
|
||||||
WANDER_VERT = 19,
|
WANDER_VERT = 19,
|
||||||
USE_LOW_GRAV = 20,
|
USE_LOW_GRAV = 20,
|
||||||
PASS_MEDIA = 21,
|
PASS_MEDIA = 21,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,73 +5,73 @@ use crate::{err::*, fixed::Fixed};
|
||||||
/// Reads a `PXpx` chunk.
|
/// Reads a `PXpx` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Physics, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Physics, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 104, start: 0, data {
|
endian: BIG, buf: b, size: 104, start: 0, data {
|
||||||
let vel_fwd = Fixed[0];
|
let vel_fwd = Fixed[0];
|
||||||
let vel_bkw = Fixed[4];
|
let vel_bkw = Fixed[4];
|
||||||
let vel_prp = Fixed[8];
|
let vel_prp = Fixed[8];
|
||||||
let acc_nrm = Fixed[12];
|
let acc_nrm = Fixed[12];
|
||||||
let dec_nrm = Fixed[16];
|
let dec_nrm = Fixed[16];
|
||||||
let dec_air = Fixed[20];
|
let dec_air = Fixed[20];
|
||||||
let acc_grv = Fixed[24];
|
let acc_grv = Fixed[24];
|
||||||
let acc_cli = Fixed[28];
|
let acc_cli = Fixed[28];
|
||||||
let vel_trm = Fixed[32];
|
let vel_trm = Fixed[32];
|
||||||
let dec_ext = Fixed[36];
|
let dec_ext = Fixed[36];
|
||||||
let acc_ang = Fixed[40];
|
let acc_ang = Fixed[40];
|
||||||
let dec_ang = Fixed[44];
|
let dec_ang = Fixed[44];
|
||||||
let vel_ang = Fixed[48];
|
let vel_ang = Fixed[48];
|
||||||
let vel_rec = Fixed[52];
|
let vel_rec = Fixed[52];
|
||||||
let fng_vel = Fixed[56];
|
let fng_vel = Fixed[56];
|
||||||
let fng_max = Fixed[60];
|
let fng_max = Fixed[60];
|
||||||
let ele_max = Fixed[64];
|
let ele_max = Fixed[64];
|
||||||
let dec_xng = Fixed[68];
|
let dec_xng = Fixed[68];
|
||||||
let stp_dta = Fixed[72];
|
let stp_dta = Fixed[72];
|
||||||
let stp_amp = Fixed[76];
|
let stp_amp = Fixed[76];
|
||||||
let ply_rad = Fixed[80];
|
let ply_rad = Fixed[80];
|
||||||
let ply_hei = Fixed[84];
|
let ply_hei = Fixed[84];
|
||||||
let ply_dhi = Fixed[88];
|
let ply_dhi = Fixed[88];
|
||||||
let ply_cam = Fixed[92];
|
let ply_cam = Fixed[92];
|
||||||
let ply_spl = Fixed[96];
|
let ply_spl = Fixed[96];
|
||||||
let ply_hcm = Fixed[100];
|
let ply_hcm = Fixed[100];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Physics{acc_ang, acc_cli, acc_grv, acc_nrm, dec_air, dec_ang, dec_ext,
|
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,
|
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,
|
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))
|
vel_bkw, vel_fwd, vel_prp, vel_rec, vel_trm}, 104))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Static physics information.
|
/// Static physics information.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Physics {
|
pub struct Physics {
|
||||||
pub acc_ang: Fixed,
|
pub acc_ang: Fixed,
|
||||||
pub acc_cli: Fixed,
|
pub acc_cli: Fixed,
|
||||||
pub acc_grv: Fixed,
|
pub acc_grv: Fixed,
|
||||||
pub acc_nrm: Fixed,
|
pub acc_nrm: Fixed,
|
||||||
pub dec_air: Fixed,
|
pub dec_air: Fixed,
|
||||||
pub dec_ang: Fixed,
|
pub dec_ang: Fixed,
|
||||||
pub dec_ext: Fixed,
|
pub dec_ext: Fixed,
|
||||||
pub dec_nrm: Fixed,
|
pub dec_nrm: Fixed,
|
||||||
pub dec_xng: Fixed,
|
pub dec_xng: Fixed,
|
||||||
pub ele_max: Fixed,
|
pub ele_max: Fixed,
|
||||||
pub fng_max: Fixed,
|
pub fng_max: Fixed,
|
||||||
pub fng_vel: Fixed,
|
pub fng_vel: Fixed,
|
||||||
pub ply_cam: Fixed,
|
pub ply_cam: Fixed,
|
||||||
pub ply_dhi: Fixed,
|
pub ply_dhi: Fixed,
|
||||||
pub ply_hcm: Fixed,
|
pub ply_hcm: Fixed,
|
||||||
pub ply_hei: Fixed,
|
pub ply_hei: Fixed,
|
||||||
pub ply_rad: Fixed,
|
pub ply_rad: Fixed,
|
||||||
pub ply_spl: Fixed,
|
pub ply_spl: Fixed,
|
||||||
pub stp_amp: Fixed,
|
pub stp_amp: Fixed,
|
||||||
pub stp_dta: Fixed,
|
pub stp_dta: Fixed,
|
||||||
pub vel_ang: Fixed,
|
pub vel_ang: Fixed,
|
||||||
pub vel_bkw: Fixed,
|
pub vel_bkw: Fixed,
|
||||||
pub vel_fwd: Fixed,
|
pub vel_fwd: Fixed,
|
||||||
pub vel_prp: Fixed,
|
pub vel_prp: Fixed,
|
||||||
pub vel_rec: Fixed,
|
pub vel_rec: Fixed,
|
||||||
pub vel_trm: Fixed,
|
pub vel_trm: Fixed,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,79 +6,79 @@ use crate::{bin::OptU16, err::*, fixed::Fixed, xfer::TransferMode};
|
||||||
/// Reads a `SIDS` chunk.
|
/// Reads a `SIDS` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Side, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Side, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 64, start: 0, data {
|
endian: BIG, buf: b, size: 64, start: 0, data {
|
||||||
let stype = u16[0] enum SideType;
|
let stype = u16[0] enum SideType;
|
||||||
let flags = u8[3] flag SideFlags;
|
let flags = u8[3] flag SideFlags;
|
||||||
let tex_pri = stex::read[4; 6];
|
let tex_pri = stex::read[4; 6];
|
||||||
let tex_sec = stex::read[10; 6];
|
let tex_sec = stex::read[10; 6];
|
||||||
let tex_tra = stex::read[16; 6];
|
let tex_tra = stex::read[16; 6];
|
||||||
let paneltyp = u16[38];
|
let paneltyp = u16[38];
|
||||||
let paneldat = i16[40];
|
let paneldat = i16[40];
|
||||||
let xfer_pri = u16[42] enum TransferMode;
|
let xfer_pri = u16[42] enum TransferMode;
|
||||||
let xfer_sec = u16[44] enum TransferMode;
|
let xfer_sec = u16[44] enum TransferMode;
|
||||||
let xfer_tra = u16[46] enum TransferMode;
|
let xfer_tra = u16[46] enum TransferMode;
|
||||||
let shade = Fixed[48];
|
let shade = Fixed[48];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
|
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
|
||||||
xfer_pri, xfer_sec, xfer_tra, shade}, 64))
|
xfer_pri, xfer_sec, xfer_tra, shade}, 64))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an old `SIDS` chunk.
|
/// Reads an old `SIDS` chunk.
|
||||||
pub fn read_old(b: &[u8]) -> ResultS<(Side, usize)>
|
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},
|
Ok((Side{tex_tra: stex::SideTex{tex_id: OptU16::none(), ..side.tex_tra},
|
||||||
shade: 0.into(),
|
shade: 0.into(),
|
||||||
flags: side.flags | SideFlags::ITEM_OPT,
|
flags: side.flags | SideFlags::ITEM_OPT,
|
||||||
..side}, siz))
|
..side}, siz))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// One side of a line segment.
|
/// One side of a line segment.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Side {
|
pub struct Side {
|
||||||
pub stype: SideType,
|
pub stype: SideType,
|
||||||
pub flags: SideFlags,
|
pub flags: SideFlags,
|
||||||
pub tex_pri: stex::SideTex,
|
pub tex_pri: stex::SideTex,
|
||||||
pub tex_sec: stex::SideTex,
|
pub tex_sec: stex::SideTex,
|
||||||
pub tex_tra: stex::SideTex,
|
pub tex_tra: stex::SideTex,
|
||||||
pub paneltyp: u16,
|
pub paneltyp: u16,
|
||||||
pub paneldat: i16,
|
pub paneldat: i16,
|
||||||
pub xfer_pri: TransferMode,
|
pub xfer_pri: TransferMode,
|
||||||
pub xfer_sec: TransferMode,
|
pub xfer_sec: TransferMode,
|
||||||
pub xfer_tra: TransferMode,
|
pub xfer_tra: TransferMode,
|
||||||
pub shade: Fixed,
|
pub shade: Fixed,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Side`.
|
/// Flags for `Side`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct SideFlags: u8 {
|
pub struct SideFlags: u8 {
|
||||||
STATUS = 0,
|
STATUS = 0,
|
||||||
PANEL = 1,
|
PANEL = 1,
|
||||||
REPAIR = 2,
|
REPAIR = 2,
|
||||||
ITEM_USE = 3,
|
ITEM_USE = 3,
|
||||||
LIGHTED = 4,
|
LIGHTED = 4,
|
||||||
CAN_DESTROY = 5,
|
CAN_DESTROY = 5,
|
||||||
HIT_ONLY = 6,
|
HIT_ONLY = 6,
|
||||||
ITEM_OPT = 7,
|
ITEM_OPT = 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The texture type of a `Side`.
|
/// The texture type of a `Side`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum SideType: u16 {
|
pub enum SideType: u16 {
|
||||||
Full = 0,
|
Full = 0,
|
||||||
High = 1,
|
High = 1,
|
||||||
Low = 2,
|
Low = 2,
|
||||||
Composite = 3,
|
Composite = 3,
|
||||||
Split = 4,
|
Split = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,31 +6,31 @@ use super::pnts;
|
||||||
/// Reads a `SideTex` object.
|
/// Reads a `SideTex` object.
|
||||||
pub fn read(b: &[u8]) -> ResultS<SideTex>
|
pub fn read(b: &[u8]) -> ResultS<SideTex>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 6, start: 0, data {
|
endian: BIG, buf: b, size: 6, start: 0, data {
|
||||||
let offs = pnts::read_o[0; 4];
|
let offs = pnts::read_o[0; 4];
|
||||||
let tex_id = OptU16[4];
|
let tex_id = OptU16[4];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(SideTex{offs, tex_id})
|
Ok(SideTex{offs, tex_id})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a `SideTex` object.
|
/// Writes a `SideTex` object.
|
||||||
pub fn write(v: &SideTex) -> Vec<u8>
|
pub fn write(v: &SideTex) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut o = Vec::with_capacity(6);
|
let mut o = Vec::with_capacity(6);
|
||||||
o.extend(pnts::write_o(v.offs));
|
o.extend(pnts::write_o(v.offs));
|
||||||
o.extend(&v.tex_id.to_be_bytes());
|
o.extend(&v.tex_id.to_be_bytes());
|
||||||
o
|
o
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The texture of a side segment.
|
/// The texture of a side segment.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct SideTex {
|
pub struct SideTex {
|
||||||
pub offs: pnts::Point,
|
pub offs: pnts::Point,
|
||||||
pub tex_id: OptU16,
|
pub tex_id: OptU16,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,50 +6,50 @@ use crate::{bin, err::*, text};
|
||||||
/// Reads a `term` chunk.
|
/// Reads a `term` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Terminal, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Terminal, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 10, start: 0, data {
|
endian: BIG, buf: b, size: 10, start: 0, data {
|
||||||
let end = u16[0] usize;
|
let end = u16[0] usize;
|
||||||
let encoded = u16[2];
|
let encoded = u16[2];
|
||||||
let lines = u16[4];
|
let lines = u16[4];
|
||||||
let group_n = u16[6] usize;
|
let group_n = u16[6] usize;
|
||||||
let face_n = u16[8] usize;
|
let face_n = u16[8] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (i_grp, x) = bin::rd_array_num(&b[10..], group_n, trmg::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 (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 = ok!(b.get(10 + x + y..end), "not enough data")?;
|
||||||
let text = if encoded != 0 {
|
let text = if encoded != 0 {
|
||||||
text::fuck_string(text)
|
text::fuck_string(text)
|
||||||
} else {
|
} else {
|
||||||
text.to_vec()
|
text.to_vec()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut groups = Vec::with_capacity(group_n);
|
let mut groups = Vec::with_capacity(group_n);
|
||||||
|
|
||||||
for grp in &i_grp {
|
for grp in &i_grp {
|
||||||
let flags = grp.flags;
|
let flags = grp.flags;
|
||||||
let ttype = grp.ttype;
|
let ttype = grp.ttype;
|
||||||
let lines = grp.lines;
|
let lines = grp.lines;
|
||||||
let beg = grp.beg;
|
let beg = grp.beg;
|
||||||
let len = grp.len;
|
let len = grp.len;
|
||||||
let text = ok!(text.get(beg..beg + len), "bad offset")?;
|
let text = ok!(text.get(beg..beg + len), "bad offset")?;
|
||||||
let text = text::mac_roman_cstr(text);
|
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.
|
/// A terminal definition, with collections of groups and faces.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Terminal {
|
pub struct Terminal {
|
||||||
pub lines: u16,
|
pub lines: u16,
|
||||||
pub groups: Vec<trmg::Group>,
|
pub groups: Vec<trmg::Group>,
|
||||||
pub faces: Vec<trmf::Face>,
|
pub faces: Vec<trmf::Face>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,69 +5,69 @@ use crate::{bin::OptU16, err::*, fixed::Unit};
|
||||||
/// Reads a `Trigger` object.
|
/// Reads a `Trigger` object.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Trigger>
|
pub fn read(b: &[u8]) -> ResultS<Trigger>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 36, start: 0, data {
|
endian: BIG, buf: b, size: 36, start: 0, data {
|
||||||
let magazine = u16[0];
|
let magazine = u16[0];
|
||||||
let typ_ammo = OptU16[2];
|
let typ_ammo = OptU16[2];
|
||||||
let tic_round = OptU16[4];
|
let tic_round = OptU16[4];
|
||||||
let tic_recover = u16[6];
|
let tic_recover = u16[6];
|
||||||
let tic_charge = u16[8];
|
let tic_charge = u16[8];
|
||||||
let recoil = Unit[10];
|
let recoil = Unit[10];
|
||||||
let snd_fire = OptU16[12];
|
let snd_fire = OptU16[12];
|
||||||
let snd_click = OptU16[14];
|
let snd_click = OptU16[14];
|
||||||
let snd_charge = OptU16[16];
|
let snd_charge = OptU16[16];
|
||||||
let snd_casing = OptU16[18];
|
let snd_casing = OptU16[18];
|
||||||
let snd_reload = OptU16[20];
|
let snd_reload = OptU16[20];
|
||||||
let snd_charged = OptU16[22];
|
let snd_charged = OptU16[22];
|
||||||
let typ_proj = u16[24];
|
let typ_proj = u16[24];
|
||||||
let theta = u16[26];
|
let theta = u16[26];
|
||||||
let dx = i16[28];
|
let dx = i16[28];
|
||||||
let dz = i16[30];
|
let dz = i16[30];
|
||||||
let typ_casing = u16[32] enum CasingType;
|
let typ_casing = u16[32] enum CasingType;
|
||||||
let burst = u16[34];
|
let burst = u16[34];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Trigger{burst, dx, dz, magazine, recoil, snd_casing, snd_charge,
|
Ok(Trigger{burst, dx, dz, magazine, recoil, snd_casing, snd_charge,
|
||||||
snd_charged, snd_click, snd_fire, snd_reload, theta, tic_charge,
|
snd_charged, snd_click, snd_fire, snd_reload, theta, tic_charge,
|
||||||
tic_recover, tic_round, typ_ammo, typ_casing, typ_proj})
|
tic_recover, tic_round, typ_ammo, typ_casing, typ_proj})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The definition of one of two triggers for a weapon.
|
/// The definition of one of two triggers for a weapon.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Trigger {
|
pub struct Trigger {
|
||||||
pub burst: u16,
|
pub burst: u16,
|
||||||
pub dx: i16,
|
pub dx: i16,
|
||||||
pub dz: i16,
|
pub dz: i16,
|
||||||
pub magazine: u16,
|
pub magazine: u16,
|
||||||
pub recoil: Unit,
|
pub recoil: Unit,
|
||||||
pub snd_casing: OptU16,
|
pub snd_casing: OptU16,
|
||||||
pub snd_charge: OptU16,
|
pub snd_charge: OptU16,
|
||||||
pub snd_charged: OptU16,
|
pub snd_charged: OptU16,
|
||||||
pub snd_click: OptU16,
|
pub snd_click: OptU16,
|
||||||
pub snd_fire: OptU16,
|
pub snd_fire: OptU16,
|
||||||
pub snd_reload: OptU16,
|
pub snd_reload: OptU16,
|
||||||
pub theta: u16,
|
pub theta: u16,
|
||||||
pub tic_charge: u16,
|
pub tic_charge: u16,
|
||||||
pub tic_recover: u16,
|
pub tic_recover: u16,
|
||||||
pub tic_round: OptU16,
|
pub tic_round: OptU16,
|
||||||
pub typ_ammo: OptU16,
|
pub typ_ammo: OptU16,
|
||||||
pub typ_casing: CasingType,
|
pub typ_casing: CasingType,
|
||||||
pub typ_proj: u16,
|
pub typ_proj: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// A bullet shell casing emitted by a weapon.
|
/// A bullet shell casing emitted by a weapon.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum CasingType: u16 {
|
pub enum CasingType: u16 {
|
||||||
Rifle = 0,
|
Rifle = 0,
|
||||||
Pistol = 1,
|
Pistol = 1,
|
||||||
PistolLeft = 2,
|
PistolLeft = 2,
|
||||||
PistolRight = 3,
|
PistolRight = 3,
|
||||||
SMG = 4,
|
SMG = 4,
|
||||||
None = 0xFFFF,
|
None = 0xFFFF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,24 +5,24 @@ use crate::err::*;
|
||||||
/// Reads a `Face`.
|
/// Reads a `Face`.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Face, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Face, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 6, start: 0, data {
|
endian: BIG, buf: b, size: 6, start: 0, data {
|
||||||
let start = u16[0] usize;
|
let start = u16[0] usize;
|
||||||
let face = u16[2];
|
let face = u16[2];
|
||||||
let color = u16[4];
|
let color = u16[4];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Face{start, face, color}, 6))
|
Ok((Face{start, face, color}, 6))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A text face.
|
/// A text face.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Face {
|
pub struct Face {
|
||||||
pub start: usize,
|
pub start: usize,
|
||||||
pub face: u16,
|
pub face: u16,
|
||||||
pub color: u16,
|
pub color: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,98 +5,98 @@ use crate::err::*;
|
||||||
/// Reads an `InterGroup`.
|
/// Reads an `InterGroup`.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(InterGroup, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(InterGroup, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 12, start: 0, data {
|
endian: BIG, buf: b, size: 12, start: 0, data {
|
||||||
let flags = u16[0] flag GroupFlags;
|
let flags = u16[0] flag GroupFlags;
|
||||||
let ttype = u16[2];
|
let ttype = u16[2];
|
||||||
let pdata = u16[4];
|
let pdata = u16[4];
|
||||||
let beg = u16[6] usize;
|
let beg = u16[6] usize;
|
||||||
let len = u16[8] usize;
|
let len = u16[8] usize;
|
||||||
let lines = u16[10];
|
let lines = u16[10];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ttype = match ttype {
|
let ttype = match ttype {
|
||||||
0 => GroupType::Logon(pdata),
|
0 => GroupType::Logon(pdata),
|
||||||
1 => GroupType::Unfinished,
|
1 => GroupType::Unfinished,
|
||||||
2 => GroupType::Success,
|
2 => GroupType::Success,
|
||||||
3 => GroupType::Failure,
|
3 => GroupType::Failure,
|
||||||
4 => GroupType::Info,
|
4 => GroupType::Info,
|
||||||
5 => GroupType::End,
|
5 => GroupType::End,
|
||||||
6 => GroupType::TeleInter(pdata),
|
6 => GroupType::TeleInter(pdata),
|
||||||
7 => GroupType::TeleIntra(pdata),
|
7 => GroupType::TeleIntra(pdata),
|
||||||
8 => GroupType::Checkpoint(pdata),
|
8 => GroupType::Checkpoint(pdata),
|
||||||
9 => GroupType::Sound(pdata),
|
9 => GroupType::Sound(pdata),
|
||||||
10 => GroupType::Movie(pdata),
|
10 => GroupType::Movie(pdata),
|
||||||
11 => GroupType::Track(pdata),
|
11 => GroupType::Track(pdata),
|
||||||
12 => GroupType::Pict(pdata),
|
12 => GroupType::Pict(pdata),
|
||||||
13 => GroupType::Logoff(pdata),
|
13 => GroupType::Logoff(pdata),
|
||||||
14 => GroupType::Camera(pdata),
|
14 => GroupType::Camera(pdata),
|
||||||
15 => GroupType::Static(pdata),
|
15 => GroupType::Static(pdata),
|
||||||
16 => GroupType::Tag(pdata),
|
16 => GroupType::Tag(pdata),
|
||||||
n => return Err(ReprError::new("GroupType", n).into()),
|
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
|
impl Default for GroupType
|
||||||
{
|
{
|
||||||
fn default() -> Self {GroupType::Unfinished}
|
fn default() -> Self {GroupType::Unfinished}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interim structure.
|
/// Interim structure.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct InterGroup {
|
pub struct InterGroup {
|
||||||
pub flags: GroupFlags,
|
pub flags: GroupFlags,
|
||||||
pub ttype: GroupType,
|
pub ttype: GroupType,
|
||||||
pub lines: u16,
|
pub lines: u16,
|
||||||
pub beg: usize,
|
pub beg: usize,
|
||||||
pub len: usize,
|
pub len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A terminal command grouping.
|
/// A terminal command grouping.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
pub flags: GroupFlags,
|
pub flags: GroupFlags,
|
||||||
pub ttype: GroupType,
|
pub ttype: GroupType,
|
||||||
pub lines: u16,
|
pub lines: u16,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The command of a `Group`.
|
/// The command of a `Group`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum GroupType {
|
pub enum GroupType {
|
||||||
Logon(u16),
|
Logon(u16),
|
||||||
Unfinished,
|
Unfinished,
|
||||||
Success,
|
Success,
|
||||||
Failure,
|
Failure,
|
||||||
Info,
|
Info,
|
||||||
End,
|
End,
|
||||||
TeleInter(u16),
|
TeleInter(u16),
|
||||||
TeleIntra(u16),
|
TeleIntra(u16),
|
||||||
Checkpoint(u16),
|
Checkpoint(u16),
|
||||||
Sound(u16),
|
Sound(u16),
|
||||||
Movie(u16),
|
Movie(u16),
|
||||||
Track(u16),
|
Track(u16),
|
||||||
Pict(u16),
|
Pict(u16),
|
||||||
Logoff(u16),
|
Logoff(u16),
|
||||||
Camera(u16),
|
Camera(u16),
|
||||||
Static(u16),
|
Static(u16),
|
||||||
Tag(u16),
|
Tag(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Group`.
|
/// Flags for `Group`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct GroupFlags: u16 {
|
pub struct GroupFlags: u16 {
|
||||||
/// Draws the picture on the right.
|
/// Draws the picture on the right.
|
||||||
DRAW_ON_RIGHT = 0,
|
DRAW_ON_RIGHT = 0,
|
||||||
/// Draws the picture in the center.
|
/// Draws the picture in the center.
|
||||||
DRAW_CENTER = 1,
|
DRAW_CENTER = 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,102 +7,102 @@ use super::trig;
|
||||||
/// Reads a `WPpx` chunk.
|
/// Reads a `WPpx` chunk.
|
||||||
pub fn read(b: &[u8]) -> ResultS<(Weapon, usize)>
|
pub fn read(b: &[u8]) -> ResultS<(Weapon, usize)>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 134, start: 0, data {
|
endian: BIG, buf: b, size: 134, start: 0, data {
|
||||||
let typ_item = u16[0];
|
let typ_item = u16[0];
|
||||||
let typ_powerup = OptU16[2];
|
let typ_powerup = OptU16[2];
|
||||||
let typ_weapon = u16[4] enum WeaponType;
|
let typ_weapon = u16[4] enum WeaponType;
|
||||||
let flags = u16[6] flag WeaponFlags;
|
let flags = u16[6] flag WeaponFlags;
|
||||||
let lit_value = Fixed[8];
|
let lit_value = Fixed[8];
|
||||||
let lit_decay = u16[12];
|
let lit_decay = u16[12];
|
||||||
let hei_idle = Fixed[14];
|
let hei_idle = Fixed[14];
|
||||||
let amp_bob = Fixed[18];
|
let amp_bob = Fixed[18];
|
||||||
let hei_kick = Fixed[22];
|
let hei_kick = Fixed[22];
|
||||||
let hei_reload = Fixed[26];
|
let hei_reload = Fixed[26];
|
||||||
let wid_idle = Fixed[30];
|
let wid_idle = Fixed[30];
|
||||||
let amp_horz = Fixed[34];
|
let amp_horz = Fixed[34];
|
||||||
let collection = u16[38];
|
let collection = u16[38];
|
||||||
let frm_idle = u16[40];
|
let frm_idle = u16[40];
|
||||||
let frm_firing = u16[42];
|
let frm_firing = u16[42];
|
||||||
let frm_reload = OptU16[44];
|
let frm_reload = OptU16[44];
|
||||||
let frm_charge = OptU16[48];
|
let frm_charge = OptU16[48];
|
||||||
let frm_charged = OptU16[50];
|
let frm_charged = OptU16[50];
|
||||||
let tic_ready = u16[52];
|
let tic_ready = u16[52];
|
||||||
let tic_load_beg = u16[54];
|
let tic_load_beg = u16[54];
|
||||||
let tic_load_mid = u16[56];
|
let tic_load_mid = u16[56];
|
||||||
let tic_load_end = u16[58];
|
let tic_load_end = u16[58];
|
||||||
let tic_powerup = u16[60];
|
let tic_powerup = u16[60];
|
||||||
let trig_pri = trig::read[62; 36];
|
let trig_pri = trig::read[62; 36];
|
||||||
let trig_sec = trig::read[98; 36];
|
let trig_sec = trig::read[98; 36];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Weapon{amp_bob, amp_horz, collection, flags, frm_charge, frm_charged,
|
Ok((Weapon{amp_bob, amp_horz, collection, flags, frm_charge, frm_charged,
|
||||||
frm_firing, frm_idle, frm_reload, hei_idle, hei_kick, hei_reload,
|
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,
|
lit_decay, lit_value, tic_load_beg, tic_load_end, tic_load_mid,
|
||||||
tic_powerup, tic_ready, trig_pri, trig_sec, typ_item,
|
tic_powerup, tic_ready, trig_pri, trig_sec, typ_item,
|
||||||
typ_powerup, typ_weapon, wid_idle}, 134))
|
typ_powerup, typ_weapon, wid_idle}, 134))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A weapon definition.
|
/// A weapon definition.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Weapon {
|
pub struct Weapon {
|
||||||
pub amp_bob: Fixed,
|
pub amp_bob: Fixed,
|
||||||
pub amp_horz: Fixed,
|
pub amp_horz: Fixed,
|
||||||
pub collection: u16,
|
pub collection: u16,
|
||||||
pub flags: WeaponFlags,
|
pub flags: WeaponFlags,
|
||||||
pub frm_charge: OptU16,
|
pub frm_charge: OptU16,
|
||||||
pub frm_charged: OptU16,
|
pub frm_charged: OptU16,
|
||||||
pub frm_firing: u16,
|
pub frm_firing: u16,
|
||||||
pub frm_idle: u16,
|
pub frm_idle: u16,
|
||||||
pub frm_reload: OptU16,
|
pub frm_reload: OptU16,
|
||||||
pub hei_idle: Fixed,
|
pub hei_idle: Fixed,
|
||||||
pub hei_kick: Fixed,
|
pub hei_kick: Fixed,
|
||||||
pub hei_reload: Fixed,
|
pub hei_reload: Fixed,
|
||||||
pub lit_decay: u16,
|
pub lit_decay: u16,
|
||||||
pub lit_value: Fixed,
|
pub lit_value: Fixed,
|
||||||
pub tic_load_beg: u16,
|
pub tic_load_beg: u16,
|
||||||
pub tic_load_end: u16,
|
pub tic_load_end: u16,
|
||||||
pub tic_load_mid: u16,
|
pub tic_load_mid: u16,
|
||||||
pub tic_powerup: u16,
|
pub tic_powerup: u16,
|
||||||
pub tic_ready: u16,
|
pub tic_ready: u16,
|
||||||
pub trig_pri: trig::Trigger,
|
pub trig_pri: trig::Trigger,
|
||||||
pub trig_sec: trig::Trigger,
|
pub trig_sec: trig::Trigger,
|
||||||
pub typ_item: u16,
|
pub typ_item: u16,
|
||||||
pub typ_powerup: OptU16,
|
pub typ_powerup: OptU16,
|
||||||
pub typ_weapon: WeaponType,
|
pub typ_weapon: WeaponType,
|
||||||
pub wid_idle: Fixed,
|
pub wid_idle: Fixed,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for a weapon.
|
/// Flags for a weapon.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct WeaponFlags: u16 {
|
pub struct WeaponFlags: u16 {
|
||||||
AUTOMATIC = 0,
|
AUTOMATIC = 0,
|
||||||
REMOVE_AFTER_USE = 1,
|
REMOVE_AFTER_USE = 1,
|
||||||
INSTANT_CASING = 2,
|
INSTANT_CASING = 2,
|
||||||
OVERLOADS = 3,
|
OVERLOADS = 3,
|
||||||
RANDOM_AMMO = 4,
|
RANDOM_AMMO = 4,
|
||||||
TEMPORARY_POWER = 5,
|
TEMPORARY_POWER = 5,
|
||||||
RELOAD_ONE_HAND = 6,
|
RELOAD_ONE_HAND = 6,
|
||||||
FIRE_OUT_OF_PHASE = 7,
|
FIRE_OUT_OF_PHASE = 7,
|
||||||
FIRE_UNDER_MEDIA = 8,
|
FIRE_UNDER_MEDIA = 8,
|
||||||
TRIGGER_SAME_AMMO = 9,
|
TRIGGER_SAME_AMMO = 9,
|
||||||
SECONDARY_FLIP = 10,
|
SECONDARY_FLIP = 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The type of functionality a weapon provides.
|
/// The type of functionality a weapon provides.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum WeaponType: u16 {
|
pub enum WeaponType: u16 {
|
||||||
Melee = 0,
|
Melee = 0,
|
||||||
Normal = 1,
|
Normal = 1,
|
||||||
DualFunc = 2,
|
DualFunc = 2,
|
||||||
DualPistol = 3,
|
DualPistol = 3,
|
||||||
Multipurpose = 4,
|
Multipurpose = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,50 +1,50 @@
|
||||||
//! Meta-information of this crate.
|
//! Meta-information of this crate.
|
||||||
|
|
||||||
macro_rules! meta_str {
|
macro_rules! meta_str {
|
||||||
($($(#[$outer:meta])* $name:ident = $e:expr;)*) => {
|
($($(#[$outer:meta])* $name:ident = $e:expr;)*) => {
|
||||||
$($(#[$outer])* pub const fn $name() -> &'static str {$e})*
|
$($(#[$outer])* pub const fn $name() -> &'static str {$e})*
|
||||||
|
|
||||||
pub mod ffi
|
pub mod ffi
|
||||||
{
|
{
|
||||||
$(
|
$(
|
||||||
doc_comment! {
|
doc_comment! {
|
||||||
concat!("FFI variant of [`",
|
concat!("FFI variant of [`",
|
||||||
stringify!($name),
|
stringify!($name),
|
||||||
"`]\n\n[`",
|
"`]\n\n[`",
|
||||||
stringify!($name),
|
stringify!($name),
|
||||||
"`]: ../fn.",
|
"`]: ../fn.",
|
||||||
stringify!($name),
|
stringify!($name),
|
||||||
".html"),
|
".html"),
|
||||||
pub const fn $name() -> crate::ffi::NT {c_str!($e)}
|
pub const fn $name() -> crate::ffi::NT {c_str!($e)}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_str! {
|
meta_str! {
|
||||||
/// The authors of this crate, `:` separated.
|
/// The authors of this crate, `:` separated.
|
||||||
authors = env!("CARGO_PKG_AUTHORS");
|
authors = env!("CARGO_PKG_AUTHORS");
|
||||||
/// The description of this crate.
|
/// The description of this crate.
|
||||||
description = env!("CARGO_PKG_DESCRIPTION");
|
description = env!("CARGO_PKG_DESCRIPTION");
|
||||||
/// The home page of this crate.
|
/// The home page of this crate.
|
||||||
homepage = env!("CARGO_PKG_HOMEPAGE");
|
homepage = env!("CARGO_PKG_HOMEPAGE");
|
||||||
/// The full license text of this crate.
|
/// The full license text of this crate.
|
||||||
license_text = include_str!("../LICENSE");
|
license_text = include_str!("../LICENSE");
|
||||||
/// The name of this crate.
|
/// The name of this crate.
|
||||||
name = env!("CARGO_PKG_NAME");
|
name = env!("CARGO_PKG_NAME");
|
||||||
/// The repository of this crate.
|
/// The repository of this crate.
|
||||||
repository = env!("CARGO_PKG_REPOSITORY");
|
repository = env!("CARGO_PKG_REPOSITORY");
|
||||||
/// The full version of this crate.
|
/// The full version of this crate.
|
||||||
version = env!("CARGO_PKG_VERSION");
|
version = env!("CARGO_PKG_VERSION");
|
||||||
/// The major version of this crate.
|
/// The major version of this crate.
|
||||||
version_major = env!("CARGO_PKG_VERSION_MAJOR");
|
version_major = env!("CARGO_PKG_VERSION_MAJOR");
|
||||||
/// The minor version of this crate.
|
/// The minor version of this crate.
|
||||||
version_minor = env!("CARGO_PKG_VERSION_MINOR");
|
version_minor = env!("CARGO_PKG_VERSION_MINOR");
|
||||||
/// The patch version of this crate.
|
/// The patch version of this crate.
|
||||||
version_patch = env!("CARGO_PKG_VERSION_PATCH");
|
version_patch = env!("CARGO_PKG_VERSION_PATCH");
|
||||||
/// The pre-release version of this crate.
|
/// The pre-release version of this crate.
|
||||||
version_pre = env!("CARGO_PKG_VERSION_PRE");
|
version_pre = env!("CARGO_PKG_VERSION_PRE");
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -14,40 +14,40 @@ pub fn read_coll_at_offset(b: &[u8],
|
||||||
ofs: u32,
|
ofs: u32,
|
||||||
len: usize) -> ResultS<Option<coll::Collection>>
|
len: usize) -> ResultS<Option<coll::Collection>>
|
||||||
{
|
{
|
||||||
if ofs != u32::max_value() {
|
if ofs != u32::max_value() {
|
||||||
let ofs = usize_from_u32(ofs);
|
let ofs = usize_from_u32(ofs);
|
||||||
let dat = ok!(b.get(ofs..ofs + len), "bad offset")?;
|
let dat = ok!(b.get(ofs..ofs + len), "bad offset")?;
|
||||||
Ok(Some(coll::read(dat)?))
|
Ok(Some(coll::read(dat)?))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read all of the collections in a Shapes file.
|
/// Read all of the collections in a Shapes file.
|
||||||
pub fn read(fp: &mut impl Read) -> ResultS<Collections>
|
pub fn read(fp: &mut impl Read) -> ResultS<Collections>
|
||||||
{
|
{
|
||||||
let mut b = Vec::new();
|
let mut b = Vec::new();
|
||||||
fp.read_to_end(&mut b)?;
|
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() {
|
for (i, co) in collections.iter_mut().enumerate() {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: &b, size: 32, start: i * 32, data {
|
endian: BIG, buf: &b, size: 32, start: i * 32, data {
|
||||||
let lo_ofs = u32[4];
|
let lo_ofs = u32[4];
|
||||||
let lo_len = u32[8] usize;
|
let lo_len = u32[8] usize;
|
||||||
let hi_ofs = u32[12];
|
let hi_ofs = u32[12];
|
||||||
let hi_len = u32[16] usize;
|
let hi_len = u32[16] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let lo = read_coll_at_offset(&b, lo_ofs, lo_len)?;
|
let lo = read_coll_at_offset(&b, lo_ofs, lo_len)?;
|
||||||
let hi = read_coll_at_offset(&b, hi_ofs, hi_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.
|
/// A collection, which may have low- and high-definition variations, or none.
|
||||||
|
|
|
@ -6,135 +6,135 @@ use super::clut;
|
||||||
/// Reads a `Bitmap`.
|
/// Reads a `Bitmap`.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Bitmap>
|
pub fn read(b: &[u8]) -> ResultS<Bitmap>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 26, start: 0, data {
|
endian: BIG, buf: b, size: 26, start: 0, data {
|
||||||
let width = u16[0] usize;
|
let width = u16[0] usize;
|
||||||
let height = u16[2] usize;
|
let height = u16[2] usize;
|
||||||
let compr = u16[4];
|
let compr = u16[4];
|
||||||
let flags = u16[6] flag BmpFlags;
|
let flags = u16[6] flag BmpFlags;
|
||||||
let depth = u16[8];
|
let depth = u16[8];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let compr = compr == u16::max_value();
|
let compr = compr == u16::max_value();
|
||||||
let alpha = flags.contains(BmpFlags::TRANSPARENT);
|
let alpha = flags.contains(BmpFlags::TRANSPARENT);
|
||||||
let cmajr = flags.contains(BmpFlags::COLUMN_MAJOR);
|
let cmajr = flags.contains(BmpFlags::COLUMN_MAJOR);
|
||||||
|
|
||||||
if depth != 8 {
|
if depth != 8 {
|
||||||
bail!("invalid bit depth (should always be 8)");
|
bail!("invalid bit depth (should always be 8)");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut bmp = Bitmap::new(width, height, alpha, cmajr);
|
let mut bmp = Bitmap::new(width, height, alpha, cmajr);
|
||||||
let mut p = 30 + if cmajr {4 * width} else {4 * height};
|
let mut p = 30 + if cmajr {4 * width} else {4 * height};
|
||||||
|
|
||||||
let scanlines = if cmajr {width} else {height};
|
let scanlines = if cmajr {width} else {height};
|
||||||
let pitch = if cmajr {height} else {width};
|
let pitch = if cmajr {height} else {width};
|
||||||
|
|
||||||
if compr {
|
if compr {
|
||||||
// compressed scanlines (transparency RLE)
|
// compressed scanlines (transparency RLE)
|
||||||
for _ in 0..scanlines {
|
for _ in 0..scanlines {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 4, start: p, data {
|
endian: BIG, buf: b, size: 4, start: p, data {
|
||||||
let fst = u16[0] usize;
|
let fst = u16[0] usize;
|
||||||
let lst = u16[2] 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 {
|
if lst < fst || fst > pitch || lst > pitch {
|
||||||
bail!("invalid compressed scanline");
|
bail!("invalid compressed scanline");
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..fst {
|
for _ in 0..fst {
|
||||||
bmp.cr.push(0);
|
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 {
|
for _ in lst..pitch {
|
||||||
bmp.cr.push(0);
|
bmp.cr.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
p += end;
|
p += end;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// simple copy
|
// simple copy
|
||||||
bmp.cr.extend(ok!(b.get(p..p + width * height), "not enough data")?);
|
bmp.cr.extend(ok!(b.get(p..p + width * height), "not enough data")?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(bmp)
|
Ok(bmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bitmap
|
impl Bitmap
|
||||||
{
|
{
|
||||||
/// Creates an empty bitmap.
|
/// Creates an empty bitmap.
|
||||||
pub fn new(w: usize, h: usize, alpha: bool, cmajr: bool) -> Self
|
pub fn new(w: usize, h: usize, alpha: bool, cmajr: bool) -> Self
|
||||||
{
|
{
|
||||||
Self{w, h, alpha, cmajr, cr: Vec::with_capacity(w * h)}
|
Self{w, h, alpha, cmajr, cr: Vec::with_capacity(w * h)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> ImageShp<'a, 'b>
|
impl<'a, 'b> ImageShp<'a, 'b>
|
||||||
{
|
{
|
||||||
/// Creates an `ImageShp` with the given bitmap.
|
/// Creates an `ImageShp` with the given bitmap.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(bmp: &'a Bitmap, clut: &'b [clut::ColorShp]) -> Self
|
pub const fn new(bmp: &'a Bitmap, clut: &'b [clut::ColorShp]) -> Self
|
||||||
{
|
{
|
||||||
Self{bmp, clut}
|
Self{bmp, clut}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image for ImageShp<'_, '_>
|
impl Image for ImageShp<'_, '_>
|
||||||
{
|
{
|
||||||
type Output = clut::ColorShp;
|
type Output = clut::ColorShp;
|
||||||
|
|
||||||
fn w(&self) -> usize {self.bmp.w}
|
fn w(&self) -> usize {self.bmp.w}
|
||||||
fn h(&self) -> usize {self.bmp.h}
|
fn h(&self) -> usize {self.bmp.h}
|
||||||
|
|
||||||
fn index(&self, x: usize, y: usize) -> &Self::Output
|
fn index(&self, x: usize, y: usize) -> &Self::Output
|
||||||
{
|
{
|
||||||
static TRANSLUCENT_COLOR: clut::ColorShp = clut::ColorShp::Translucent;
|
static TRANSLUCENT_COLOR: clut::ColorShp = clut::ColorShp::Translucent;
|
||||||
|
|
||||||
let cr = usize::from(if self.bmp.cmajr {
|
let cr = usize::from(if self.bmp.cmajr {
|
||||||
self.bmp.cr[y + x * self.bmp.h]
|
self.bmp.cr[y + x * self.bmp.h]
|
||||||
} else {
|
} else {
|
||||||
self.bmp.cr[x + y * self.bmp.w]
|
self.bmp.cr[x + y * self.bmp.w]
|
||||||
});
|
});
|
||||||
|
|
||||||
if self.bmp.alpha && cr == 0 {
|
if self.bmp.alpha && cr == 0 {
|
||||||
&TRANSLUCENT_COLOR
|
&TRANSLUCENT_COLOR
|
||||||
} else {
|
} else {
|
||||||
self.clut.get(cr).unwrap_or(&TRANSLUCENT_COLOR)
|
self.clut.get(cr).unwrap_or(&TRANSLUCENT_COLOR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An unpacked Shape bitmap.
|
/// An unpacked Shape bitmap.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Bitmap {
|
pub struct Bitmap {
|
||||||
w: usize,
|
w: usize,
|
||||||
h: usize,
|
h: usize,
|
||||||
cr: Vec<u8>,
|
cr: Vec<u8>,
|
||||||
alpha: bool,
|
alpha: bool,
|
||||||
cmajr: bool,
|
cmajr: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An image from a Shape. This mainly just exists so that `Bitmap` can use the
|
/// An image from a Shape. This mainly just exists so that `Bitmap` can use the
|
||||||
/// `Image` trait.
|
/// `Image` trait.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct ImageShp<'a, 'b> {
|
pub struct ImageShp<'a, 'b> {
|
||||||
bmp: &'a Bitmap,
|
bmp: &'a Bitmap,
|
||||||
clut: &'b [clut::ColorShp],
|
clut: &'b [clut::ColorShp],
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
pub struct BmpFlags: u16 {
|
pub struct BmpFlags: u16 {
|
||||||
TRANSPARENT = 14,
|
TRANSPARENT = 14,
|
||||||
COLUMN_MAJOR = 15,
|
COLUMN_MAJOR = 15,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,27 +5,27 @@ use crate::{err::*, image::Color};
|
||||||
/// Reads a color from a color table into `clut`.
|
/// Reads a color from a color table into `clut`.
|
||||||
pub fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
|
pub fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 8, start: 0, data {
|
endian: BIG, buf: b, size: 8, start: 0, data {
|
||||||
let flag = u8[0];
|
let flag = u8[0];
|
||||||
let ind = u8[1];
|
let ind = u8[1];
|
||||||
let r = u16[2];
|
let r = u16[2];
|
||||||
let g = u16[4];
|
let g = u16[4];
|
||||||
let b = u16[6];
|
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 {
|
*cr = match flag {
|
||||||
128 => ColorShp::Lit {r, g, b},
|
128 => ColorShp::Lit {r, g, b},
|
||||||
0 => ColorShp::Opaque{r, g, b},
|
0 => ColorShp::Opaque{r, g, b},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(err_msg("invalid flag in color"));
|
return Err(err_msg("invalid flag in color"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads color tables from `b`.
|
/// Reads color tables from `b`.
|
||||||
|
@ -34,78 +34,78 @@ pub fn read(b: &[u8],
|
||||||
tab_num: usize,
|
tab_num: usize,
|
||||||
clr_num: usize) -> ResultS<Vec<Clut>>
|
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 v = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
for clut in v.iter_mut().take(tab_num) {
|
for clut in v.iter_mut().take(tab_num) {
|
||||||
for _ in 0..clr_num {
|
for _ in 0..clr_num {
|
||||||
read_color(ok!(b.get(p..p + 8), "not enough data")?, clut)?;
|
read_color(ok!(b.get(p..p + 8), "not enough data")?, clut)?;
|
||||||
p += 8;
|
p += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Color for ColorShp
|
impl Color for ColorShp
|
||||||
{
|
{
|
||||||
fn r(&self) -> u16
|
fn r(&self) -> u16
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
ColorShp::Translucent => 0,
|
ColorShp::Translucent => 0,
|
||||||
ColorShp::Opaque{r, ..} |
|
ColorShp::Opaque{r, ..} |
|
||||||
ColorShp::Lit {r, ..} => r,
|
ColorShp::Lit {r, ..} => r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn g(&self) -> u16
|
fn g(&self) -> u16
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
ColorShp::Translucent => 0,
|
ColorShp::Translucent => 0,
|
||||||
ColorShp::Opaque{g, ..} |
|
ColorShp::Opaque{g, ..} |
|
||||||
ColorShp::Lit {g, ..} => g,
|
ColorShp::Lit {g, ..} => g,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn b(&self) -> u16
|
fn b(&self) -> u16
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
ColorShp::Translucent => 0,
|
ColorShp::Translucent => 0,
|
||||||
ColorShp::Opaque{b, ..} |
|
ColorShp::Opaque{b, ..} |
|
||||||
ColorShp::Lit {b, ..} => b,
|
ColorShp::Lit {b, ..} => b,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn a(&self) -> u16
|
fn a(&self) -> u16
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
ColorShp::Translucent => 0,
|
ColorShp::Translucent => 0,
|
||||||
ColorShp::Opaque{..} |
|
ColorShp::Opaque{..} |
|
||||||
ColorShp::Lit {..} => u16::max_value(),
|
ColorShp::Lit {..} => u16::max_value(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A color in a `Clut`.
|
/// A color in a `Clut`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum ColorShp {
|
pub enum ColorShp {
|
||||||
/// A completely translucent color.
|
/// A completely translucent color.
|
||||||
Translucent,
|
Translucent,
|
||||||
|
|
||||||
/// An opaque color which may be shaded.
|
/// An opaque color which may be shaded.
|
||||||
Opaque{/** The red component. */ r: u16,
|
Opaque{/** The red component. */ r: u16,
|
||||||
/** The green component. */ g: u16,
|
/** The green component. */ g: u16,
|
||||||
/** The blue component. */ b: u16},
|
/** The blue component. */ b: u16},
|
||||||
|
|
||||||
/// An opaque color which may not be shaded.
|
/// An opaque color which may not be shaded.
|
||||||
Lit{/** The red component. */ r: u16,
|
Lit{/** The red component. */ r: u16,
|
||||||
/** The green component. */ g: u16,
|
/** The green component. */ g: u16,
|
||||||
/** The blue component. */ b: u16},
|
/** The blue component. */ b: u16},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A color collection.
|
/// A color collection.
|
||||||
|
|
|
@ -6,63 +6,63 @@ use super::{bmap, clut, fram, sequ};
|
||||||
/// Reads a `Collection`.
|
/// Reads a `Collection`.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Collection>
|
pub fn read(b: &[u8]) -> ResultS<Collection>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 544, start: 0, data {
|
endian: BIG, buf: b, size: 544, start: 0, data {
|
||||||
let version = u16[0];
|
let version = u16[0];
|
||||||
let cl_type = u16[2] enum CollectionType;
|
let cl_type = u16[2] enum CollectionType;
|
||||||
let clr_num = u16[6] usize;
|
let clr_num = u16[6] usize;
|
||||||
let tab_num = u16[8] usize;
|
let tab_num = u16[8] usize;
|
||||||
let tab_ofs = u32[10] usize;
|
let tab_ofs = u32[10] usize;
|
||||||
let seq_num = u16[14] usize;
|
let seq_num = u16[14] usize;
|
||||||
let seq_ofs = u32[16] usize;
|
let seq_ofs = u32[16] usize;
|
||||||
let frm_num = u16[20] usize;
|
let frm_num = u16[20] usize;
|
||||||
let frm_ofs = u32[22] usize;
|
let frm_ofs = u32[22] usize;
|
||||||
let bmp_num = u16[26] usize;
|
let bmp_num = u16[26] usize;
|
||||||
let bmp_ofs = u32[28] usize;
|
let bmp_ofs = u32[28] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if version != 3 {
|
if version != 3 {
|
||||||
bail!("invalid collection definition");
|
bail!("invalid collection definition");
|
||||||
}
|
}
|
||||||
|
|
||||||
let tabs = clut::read(b, tab_ofs, tab_num, clr_num)?;
|
let tabs = clut::read(b, tab_ofs, tab_num, clr_num)?;
|
||||||
let bmps = rd_ofstable(b, bmp_ofs, bmp_num, bmap::read)?;
|
let bmps = rd_ofstable(b, bmp_ofs, bmp_num, bmap::read)?;
|
||||||
let frms = rd_ofstable(b, frm_ofs, frm_num, fram::read)?;
|
let frms = rd_ofstable(b, frm_ofs, frm_num, fram::read)?;
|
||||||
let seqs = rd_ofstable(b, seq_ofs, seq_num, sequ::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.
|
/// A collection of color tables, bitmaps, frames and sequences.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Collection {
|
pub struct Collection {
|
||||||
/// The type of collection this is.
|
/// The type of collection this is.
|
||||||
pub ctyp: CollectionType,
|
pub ctyp: CollectionType,
|
||||||
|
|
||||||
/// All of the color tables in this collection.
|
/// All of the color tables in this collection.
|
||||||
pub tabs: Vec<clut::Clut>,
|
pub tabs: Vec<clut::Clut>,
|
||||||
|
|
||||||
/// All of the bitmaps in this collection.
|
/// All of the bitmaps in this collection.
|
||||||
pub bmps: Vec<bmap::Bitmap>,
|
pub bmps: Vec<bmap::Bitmap>,
|
||||||
|
|
||||||
/// All of the frames in this collection.
|
/// All of the frames in this collection.
|
||||||
pub frms: Vec<fram::Frame>,
|
pub frms: Vec<fram::Frame>,
|
||||||
|
|
||||||
/// All of the sequences in this collection.
|
/// All of the sequences in this collection.
|
||||||
pub seqs: Vec<sequ::Sequence>,
|
pub seqs: Vec<sequ::Sequence>,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The type of a collection.
|
/// The type of a collection.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum CollectionType: u16 {
|
pub enum CollectionType: u16 {
|
||||||
Unused = 0,
|
Unused = 0,
|
||||||
Wall = 1,
|
Wall = 1,
|
||||||
Object = 2,
|
Object = 2,
|
||||||
Interface = 3,
|
Interface = 3,
|
||||||
Scenery = 4,
|
Scenery = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,66 +5,66 @@ use crate::{err::*, fixed::*};
|
||||||
/// Reads a `Frame`.
|
/// Reads a `Frame`.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Frame>
|
pub fn read(b: &[u8]) -> ResultS<Frame>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 36, start: 0, data {
|
endian: BIG, buf: b, size: 36, start: 0, data {
|
||||||
let flags = u16[0] flag FrameFlags;
|
let flags = u16[0] flag FrameFlags;
|
||||||
let min_lt = Fixed[2];
|
let min_lt = Fixed[2];
|
||||||
let bmp_ind = u16[6] usize;
|
let bmp_ind = u16[6] usize;
|
||||||
let wrl_l = Unit[16];
|
let wrl_l = Unit[16];
|
||||||
let wrl_r = Unit[18];
|
let wrl_r = Unit[18];
|
||||||
let wrl_t = Unit[20];
|
let wrl_t = Unit[20];
|
||||||
let wrl_b = Unit[22];
|
let wrl_b = Unit[22];
|
||||||
let wrl_x = Unit[24];
|
let wrl_x = Unit[24];
|
||||||
let wrl_y = Unit[26];
|
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.
|
/// A frame, also known as a low level shape.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
/// The flags for this frame.
|
/// The flags for this frame.
|
||||||
pub flags: FrameFlags,
|
pub flags: FrameFlags,
|
||||||
|
|
||||||
/// The minimum light level for this frame.
|
/// The minimum light level for this frame.
|
||||||
pub min_lt: Fixed,
|
pub min_lt: Fixed,
|
||||||
|
|
||||||
/// The index of the bitmap this frame uses.
|
/// The index of the bitmap this frame uses.
|
||||||
pub bmp_ind: usize,
|
pub bmp_ind: usize,
|
||||||
|
|
||||||
/// The left translation for this frame.
|
/// The left translation for this frame.
|
||||||
pub wrl_l: Unit,
|
pub wrl_l: Unit,
|
||||||
|
|
||||||
/// The right translation for this frame.
|
/// The right translation for this frame.
|
||||||
pub wrl_r: Unit,
|
pub wrl_r: Unit,
|
||||||
|
|
||||||
/// The top translation for this frame.
|
/// The top translation for this frame.
|
||||||
pub wrl_t: Unit,
|
pub wrl_t: Unit,
|
||||||
|
|
||||||
/// The bottom translation for this frame.
|
/// The bottom translation for this frame.
|
||||||
pub wrl_b: Unit,
|
pub wrl_b: Unit,
|
||||||
|
|
||||||
/// The X translation for this frame.
|
/// The X translation for this frame.
|
||||||
pub wrl_x: Unit,
|
pub wrl_x: Unit,
|
||||||
|
|
||||||
/// The Y translation for this frame.
|
/// The Y translation for this frame.
|
||||||
pub wrl_y: Unit,
|
pub wrl_y: Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `Frame`.
|
/// Flags for `Frame`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct FrameFlags: u16 {
|
pub struct FrameFlags: u16 {
|
||||||
/// The player's torso will obscure the player's legs.
|
/// The player's torso will obscure the player's legs.
|
||||||
OBSCURE = 13,
|
OBSCURE = 13,
|
||||||
/// The bitmap will be flipped on the vertical axis.
|
/// The bitmap will be flipped on the vertical axis.
|
||||||
FLIP_Y = 14,
|
FLIP_Y = 14,
|
||||||
/// The bitmap will be flipped on the horizontal axis.
|
/// The bitmap will be flipped on the horizontal axis.
|
||||||
FLIP_X = 15,
|
FLIP_X = 15,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -7,80 +7,80 @@ use crate::{bin::OptU16, err::*,
|
||||||
/// Reads a `Sequence`.
|
/// Reads a `Sequence`.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Sequence>
|
pub fn read(b: &[u8]) -> ResultS<Sequence>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 88, start: 0, data {
|
endian: BIG, buf: b, size: 88, start: 0, data {
|
||||||
let name = u8[4; 34];
|
let name = u8[4; 34];
|
||||||
let v_type = u16[38] enum ViewType;
|
let v_type = u16[38] enum ViewType;
|
||||||
let frames = u16[40];
|
let frames = u16[40];
|
||||||
let ticks = u16[42];
|
let ticks = u16[42];
|
||||||
let key = u16[44];
|
let key = u16[44];
|
||||||
let xfer = u16[46] enum TransferMode;
|
let xfer = u16[46] enum TransferMode;
|
||||||
let xfer_pd = u16[48];
|
let xfer_pd = u16[48];
|
||||||
let snd_beg = OptU16[50];
|
let snd_beg = OptU16[50];
|
||||||
let snd_key = OptU16[52];
|
let snd_key = OptU16[52];
|
||||||
let snd_end = OptU16[54];
|
let snd_end = OptU16[54];
|
||||||
let loop_f = u16[58];
|
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,
|
Ok(Sequence{name, v_type, frames, ticks, key, xfer, xfer_pd, snd_beg,
|
||||||
snd_key, snd_end, loop_f})
|
snd_key, snd_end, loop_f})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sequence, also known as a high level shape.
|
/// A sequence, also known as a high level shape.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Sequence {
|
pub struct Sequence {
|
||||||
/// The display name for this sequence.
|
/// The display name for this sequence.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
/// The view type for each frame in this sequence.
|
/// The view type for each frame in this sequence.
|
||||||
pub v_type: ViewType,
|
pub v_type: ViewType,
|
||||||
|
|
||||||
/// The number of frames in this sequence.
|
/// The number of frames in this sequence.
|
||||||
pub frames: u16,
|
pub frames: u16,
|
||||||
|
|
||||||
/// The number of ticks each frame in this sequence takes.
|
/// The number of ticks each frame in this sequence takes.
|
||||||
pub ticks: u16,
|
pub ticks: u16,
|
||||||
|
|
||||||
/// The key frame index for this sequence.
|
/// The key frame index for this sequence.
|
||||||
pub key: u16,
|
pub key: u16,
|
||||||
|
|
||||||
/// The transfer mode to play over this sequence.
|
/// The transfer mode to play over this sequence.
|
||||||
pub xfer: TransferMode,
|
pub xfer: TransferMode,
|
||||||
|
|
||||||
/// The period in game ticks the transfer mode plays over.
|
/// The period in game ticks the transfer mode plays over.
|
||||||
pub xfer_pd: u16,
|
pub xfer_pd: u16,
|
||||||
|
|
||||||
/// The sound to play at the beginning of this sequence.
|
/// The sound to play at the beginning of this sequence.
|
||||||
pub snd_beg: OptU16,
|
pub snd_beg: OptU16,
|
||||||
|
|
||||||
/// The sound to play at the key frame of this sequence.
|
/// The sound to play at the key frame of this sequence.
|
||||||
pub snd_key: OptU16,
|
pub snd_key: OptU16,
|
||||||
|
|
||||||
/// The sound to play at the end of this sequence.
|
/// The sound to play at the end of this sequence.
|
||||||
pub snd_end: OptU16,
|
pub snd_end: OptU16,
|
||||||
|
|
||||||
/// Which frame to loop on.
|
/// Which frame to loop on.
|
||||||
pub loop_f: u16,
|
pub loop_f: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The type of or number of views for a sequence.
|
/// The type of or number of views for a sequence.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum ViewType: u16 {
|
pub enum ViewType: u16 {
|
||||||
Anim = 1,
|
Anim = 1,
|
||||||
Anim8from2 = 2,
|
Anim8from2 = 2,
|
||||||
Anim4from3 = 3,
|
Anim4from3 = 3,
|
||||||
Anim4 = 4,
|
Anim4 = 4,
|
||||||
Anim8from5 = 5,
|
Anim8from5 = 5,
|
||||||
Anim8 = 8,
|
Anim8 = 8,
|
||||||
Anim5from3 = 9,
|
Anim5from3 = 9,
|
||||||
Still = 10,
|
Still = 10,
|
||||||
Anim5 = 11,
|
Anim5 = 11,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -9,43 +9,43 @@ use std::{collections::BTreeMap, io::prelude::*};
|
||||||
/// Reads all sounds from a Sound file.
|
/// Reads all sounds from a Sound file.
|
||||||
pub fn read(fp: &mut impl Read) -> ResultS<Vec<SoundTable>>
|
pub fn read(fp: &mut impl Read) -> ResultS<Vec<SoundTable>>
|
||||||
{
|
{
|
||||||
let mut b = Vec::new();
|
let mut b = Vec::new();
|
||||||
fp.read_to_end(&mut b)?;
|
fp.read_to_end(&mut b)?;
|
||||||
|
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: &b, size: 260, start: 0, data {
|
endian: BIG, buf: &b, size: 260, start: 0, data {
|
||||||
let version = u32[0];
|
let version = u32[0];
|
||||||
let magic = Ident[4];
|
let magic = Ident[4];
|
||||||
let src_num = u16[8] usize;
|
let src_num = u16[8] usize;
|
||||||
let snd_num = u16[10] usize;
|
let snd_num = u16[10] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if version != 1 || magic != b"snd2" {
|
if version != 1 || magic != b"snd2" {
|
||||||
bail!("bad sound header");
|
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 {
|
for i in 0..src_num {
|
||||||
let p = 260 + i * 64;
|
let p = 260 + i * 64;
|
||||||
|
|
||||||
let mut st = SoundTable::new();
|
let mut st = SoundTable::new();
|
||||||
|
|
||||||
for _ in 0..snd_num {
|
for _ in 0..snd_num {
|
||||||
if let Some((ofs, idx, mut def)) = defs::read(&b[p..p + 64])? {
|
if let Some((ofs, idx, mut def)) = defs::read(&b[p..p + 64])? {
|
||||||
for &ofs in &ofs {
|
for &ofs in &ofs {
|
||||||
def.sounds.push(snds::read(&b[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.
|
/// A table of sound definitions.
|
||||||
|
|
|
@ -5,92 +5,92 @@ use crate::{bin::{u32b, usize_from_u32}, err::*, fixed::*, sound::Sound16};
|
||||||
/// Reads a sound definition.
|
/// Reads a sound definition.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
|
pub fn read(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 64, start: 0, data {
|
endian: BIG, buf: b, size: 64, start: 0, data {
|
||||||
let index = u16[0];
|
let index = u16[0];
|
||||||
let volume = u16[2] enum Volume;
|
let volume = u16[2] enum Volume;
|
||||||
let flags = u16[4] flag SoundFlags;
|
let flags = u16[4] flag SoundFlags;
|
||||||
let chance = u16[6];
|
let chance = u16[6];
|
||||||
let pitch_lo = Fixed[8];
|
let pitch_lo = Fixed[8];
|
||||||
let pitch_hi = Fixed[12];
|
let pitch_hi = Fixed[12];
|
||||||
let n_sounds = u16[16] usize;
|
let n_sounds = u16[16] usize;
|
||||||
let grp_ofs = u32[20] usize;
|
let grp_ofs = u32[20] usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == u16::max_value() {
|
if index == u16::max_value() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if n_sounds > 5 {
|
if n_sounds > 5 {
|
||||||
bail!("too many sounds");
|
bail!("too many sounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ofs = Vec::with_capacity(n_sounds);
|
let mut ofs = Vec::with_capacity(n_sounds);
|
||||||
let mut p = 36;
|
let mut p = 36;
|
||||||
|
|
||||||
for _ in 0..n_sounds {
|
for _ in 0..n_sounds {
|
||||||
ofs.push(grp_ofs + usize_from_u32(u32b(&b[p..])));
|
ofs.push(grp_ofs + usize_from_u32(u32b(&b[p..])));
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sounds = Vec::with_capacity(n_sounds);
|
let sounds = Vec::with_capacity(n_sounds);
|
||||||
|
|
||||||
Ok(Some((ofs, index,
|
Ok(Some((ofs, index,
|
||||||
SoundDef{volume, flags, chance, pitch_lo, pitch_hi, sounds})))
|
SoundDef{volume, flags, chance, pitch_lo, pitch_hi, sounds})))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sound definition containing one, many or no sounds.
|
/// A sound definition containing one, many or no sounds.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct SoundDef {
|
pub struct SoundDef {
|
||||||
/// The volume type for this sound.
|
/// The volume type for this sound.
|
||||||
pub volume: Volume,
|
pub volume: Volume,
|
||||||
|
|
||||||
/// The flags for this sound.
|
/// The flags for this sound.
|
||||||
pub flags: SoundFlags,
|
pub flags: SoundFlags,
|
||||||
|
|
||||||
/// The chance out of `u16::max_value()` that this sound will not play.
|
/// The chance out of `u16::max_value()` that this sound will not play.
|
||||||
pub chance: u16,
|
pub chance: u16,
|
||||||
|
|
||||||
/// The low random pitch bound.
|
/// The low random pitch bound.
|
||||||
pub pitch_lo: Fixed,
|
pub pitch_lo: Fixed,
|
||||||
|
|
||||||
/// The high random pitch bound.
|
/// The high random pitch bound.
|
||||||
pub pitch_hi: Fixed,
|
pub pitch_hi: Fixed,
|
||||||
|
|
||||||
/// All of the sounds in this collection.
|
/// All of the sounds in this collection.
|
||||||
pub sounds: Vec<Sound16>,
|
pub sounds: Vec<Sound16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_bitfield! {
|
c_bitfield! {
|
||||||
/// Flags for `SoundDef`.
|
/// Flags for `SoundDef`.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub struct SoundFlags: u16 {
|
pub struct SoundFlags: u16 {
|
||||||
/// The sound will not restart when trying to play over itself.
|
/// The sound will not restart when trying to play over itself.
|
||||||
NO_RESTART = 0,
|
NO_RESTART = 0,
|
||||||
/// The sound will not switch channels when trying to play over itself.
|
/// The sound will not switch channels when trying to play over itself.
|
||||||
NO_CHANNEL_SWITCH = 1,
|
NO_CHANNEL_SWITCH = 1,
|
||||||
/// The pitch variance will be halved.
|
/// The pitch variance will be halved.
|
||||||
LESS_PITCH_CHANGE = 2,
|
LESS_PITCH_CHANGE = 2,
|
||||||
/// The pitch variance will be nullified.
|
/// The pitch variance will be nullified.
|
||||||
NO_PITCH_CHANGE = 3,
|
NO_PITCH_CHANGE = 3,
|
||||||
/// The sound will play even when completely obstructed by walls.
|
/// The sound will play even when completely obstructed by walls.
|
||||||
NO_OBSTRUCTION = 4,
|
NO_OBSTRUCTION = 4,
|
||||||
/// The sound will play even when completely obstructed by media.
|
/// The sound will play even when completely obstructed by media.
|
||||||
NO_MEDIA_OBSTRUCT = 5,
|
NO_MEDIA_OBSTRUCT = 5,
|
||||||
/// The sound will have special stereo effects.
|
/// The sound will have special stereo effects.
|
||||||
AMBIENT = 6,
|
AMBIENT = 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// The type of volume this sound has.
|
/// The type of volume this sound has.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum Volume: u16 {
|
pub enum Volume: u16 {
|
||||||
Quiet = 0,
|
Quiet = 0,
|
||||||
Normal = 1,
|
Normal = 1,
|
||||||
Loud = 2,
|
Loud = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,43 +5,43 @@ use crate::{err::*, sound::Sound16};
|
||||||
/// Reads a sound.
|
/// Reads a sound.
|
||||||
pub fn read(b: &[u8]) -> ResultS<Sound16>
|
pub fn read(b: &[u8]) -> ResultS<Sound16>
|
||||||
{
|
{
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 21, start: 0, data {
|
endian: BIG, buf: b, size: 21, start: 0, data {
|
||||||
let len = u32[4] usize;
|
let len = u32[4] usize;
|
||||||
let rate = u16[8];
|
let rate = u16[8];
|
||||||
let lp_beg = u32[12] usize;
|
let lp_beg = u32[12] usize;
|
||||||
let lp_end = u32[16] usize;
|
let lp_end = u32[16] usize;
|
||||||
let magic = u8[20];
|
let magic = u8[20];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match magic {
|
match magic {
|
||||||
0 => {
|
0 => {
|
||||||
let stream = &b[22..22 + len];
|
let stream = &b[22..22 + len];
|
||||||
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
|
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
|
||||||
}
|
}
|
||||||
0xFF => {
|
0xFF => {
|
||||||
read_data! {
|
read_data! {
|
||||||
endian: BIG, buf: b, size: 42, start: 22, data {
|
endian: BIG, buf: b, size: 42, start: 22, data {
|
||||||
let len = u32[0] usize;
|
let len = u32[0] usize;
|
||||||
let bps = u16[26];
|
let bps = u16[26];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match bps {
|
match bps {
|
||||||
16 => {
|
16 => {
|
||||||
let stream = &b[63..63 + len * 2];
|
let stream = &b[63..63 + len * 2];
|
||||||
Ok(Sound16::new_from_16(rate, lp_beg, lp_end, stream))
|
Ok(Sound16::new_from_16(rate, lp_beg, lp_end, stream))
|
||||||
}
|
}
|
||||||
8 => {
|
8 => {
|
||||||
let stream = &b[63..63 + len];
|
let stream = &b[63..63 + len];
|
||||||
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
|
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
|
||||||
}
|
}
|
||||||
_ => bail!("bad bits per sample"),
|
_ => bail!("bad bits per sample"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bail!("invalid magic number"),
|
_ => bail!("invalid magic number"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// 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.
|
/// Any PCM stream which may be represented as a 16-bit PCM stream.
|
||||||
pub trait Sound
|
pub trait Sound
|
||||||
{
|
{
|
||||||
/// Returns the sample rate.
|
/// Returns the sample rate.
|
||||||
fn rate(&self) -> u16;
|
fn rate(&self) -> u16;
|
||||||
|
|
||||||
/// Returns the number of samples.
|
/// Returns the number of samples.
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
|
|
||||||
/// Returns the `n`th sample.
|
/// Returns the `n`th sample.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `n` exceeds the length of this sound.
|
/// Panics if `n` exceeds the length of this sound.
|
||||||
fn index(&self, n: usize) -> i16;
|
fn index(&self, n: usize) -> i16;
|
||||||
|
|
||||||
/// Returns the number of the first sample of the loop, or `0`.
|
/// Returns the number of the first sample of the loop, or `0`.
|
||||||
fn lp_beg(&self) -> usize;
|
fn lp_beg(&self) -> usize;
|
||||||
|
|
||||||
/// Returns the number of the last sample of the loop, or `0`.
|
/// Returns the number of the last sample of the loop, or `0`.
|
||||||
fn lp_end(&self) -> usize;
|
fn lp_end(&self) -> usize;
|
||||||
|
|
||||||
/// Returns `true` if there are no samples in this sound.
|
/// Returns `true` if there are no samples in this sound.
|
||||||
fn is_empty(&self) -> bool {self.len() == 0}
|
fn is_empty(&self) -> bool {self.len() == 0}
|
||||||
|
|
||||||
/// The same as `index`, but will not panic if out of bounds.
|
/// The same as `index`, but will not panic if out of bounds.
|
||||||
fn get(&self, n: usize) -> Option<i16>
|
fn get(&self, n: usize) -> Option<i16>
|
||||||
{
|
{
|
||||||
if n < self.len() {
|
if n < self.len() {
|
||||||
Some(self.index(n))
|
Some(self.index(n))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sound16
|
impl Sound16
|
||||||
{
|
{
|
||||||
/// Creates a new `Sound16`.
|
/// Creates a new `Sound16`.
|
||||||
pub fn new(rate: u16, lp_beg: usize, lp_end: usize, len: usize) -> Self
|
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)}
|
Self{rate, lp_beg, lp_end, data: Vec::with_capacity(len)}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `Sound16` from an unsigned 8-bit stream.
|
/// 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
|
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());
|
let mut snd = Self::new(rate, lp_beg, lp_end, b.len());
|
||||||
|
|
||||||
for &sample in b {
|
for &sample in b {
|
||||||
snd.data.push(Self::sample_from_8(sample));
|
snd.data.push(Self::sample_from_8(sample));
|
||||||
}
|
}
|
||||||
|
|
||||||
snd
|
snd
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `Sound16` from a signed 16-bit stream.
|
/// 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
|
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);
|
let mut snd = Self::new(rate, lp_beg, lp_end, b.len() / 2);
|
||||||
|
|
||||||
for i in (0..b.len()).step_by(2) {
|
for i in (0..b.len()).step_by(2) {
|
||||||
snd.data.push(i16::from_le_bytes([b[i], b[i + 1]]));
|
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.
|
/// 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}
|
pub fn sample_from_8(sample: u8) -> i16 {(i16::from(sample) - 0x80) << 8}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sound for Sound16
|
impl Sound for Sound16
|
||||||
{
|
{
|
||||||
fn rate(&self) -> u16 {self.rate}
|
fn rate(&self) -> u16 {self.rate}
|
||||||
fn len(&self) -> usize {self.data.len()}
|
fn len(&self) -> usize {self.data.len()}
|
||||||
fn index(&self, p: usize) -> i16 {self.data[p]}
|
fn index(&self, p: usize) -> i16 {self.data[p]}
|
||||||
fn lp_beg(&self) -> usize {self.lp_beg}
|
fn lp_beg(&self) -> usize {self.lp_beg}
|
||||||
fn lp_end(&self) -> usize {self.lp_end}
|
fn lp_end(&self) -> usize {self.lp_end}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 16-bit PCM stream.
|
/// A 16-bit PCM stream.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Sound16 {
|
pub struct Sound16 {
|
||||||
rate: u16,
|
rate: u16,
|
||||||
lp_beg: usize,
|
lp_beg: usize,
|
||||||
lp_end: usize,
|
lp_end: usize,
|
||||||
|
|
||||||
/// The raw signed PCM data of this sound.
|
/// The raw signed PCM data of this sound.
|
||||||
pub data: Vec<i16>,
|
pub data: Vec<i16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -10,36 +10,36 @@ use std::io;
|
||||||
/// Errors if `out` cannot be written to.
|
/// Errors if `out` cannot be written to.
|
||||||
pub fn write_wav(out: &mut impl io::Write, snd: &impl Sound) -> ResultS<()>
|
pub fn write_wav(out: &mut impl io::Write, snd: &impl Sound) -> ResultS<()>
|
||||||
{
|
{
|
||||||
let smp_rate = u32::from(snd.rate());
|
let smp_rate = u32::from(snd.rate());
|
||||||
let smp_size = smp_rate * 2;
|
let smp_size = smp_rate * 2;
|
||||||
let dat_size = snd.len() as u32 * 2;
|
let dat_size = snd.len() as u32 * 2;
|
||||||
|
|
||||||
out.write_all(b"RIFF")?;
|
out.write_all(b"RIFF")?;
|
||||||
out.write_all(&u32::to_le_bytes(36 + dat_size))?;
|
out.write_all(&u32::to_le_bytes(36 + dat_size))?;
|
||||||
out.write_all(b"WAVE")?;
|
out.write_all(b"WAVE")?;
|
||||||
|
|
||||||
out.write_all(b"fmt ")?;
|
out.write_all(b"fmt ")?;
|
||||||
out.write_all(&u32::to_le_bytes(16))?;
|
out.write_all(&u32::to_le_bytes(16))?;
|
||||||
// PCM
|
// PCM
|
||||||
out.write_all(&u16::to_le_bytes(1))?;
|
out.write_all(&u16::to_le_bytes(1))?;
|
||||||
// mono
|
// mono
|
||||||
out.write_all(&u16::to_le_bytes(1))?;
|
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_rate))?;
|
||||||
out.write_all(&u32::to_le_bytes(smp_size))?;
|
out.write_all(&u32::to_le_bytes(smp_size))?;
|
||||||
// block alignment
|
// block alignment
|
||||||
out.write_all(&u16::to_le_bytes(2))?;
|
out.write_all(&u16::to_le_bytes(2))?;
|
||||||
// bits per sample
|
// bits per sample
|
||||||
out.write_all(&u16::to_le_bytes(16))?;
|
out.write_all(&u16::to_le_bytes(16))?;
|
||||||
|
|
||||||
out.write_all(b"data")?;
|
out.write_all(b"data")?;
|
||||||
out.write_all(&u32::to_le_bytes(dat_size))?;
|
out.write_all(&u32::to_le_bytes(dat_size))?;
|
||||||
|
|
||||||
for p in 0..snd.len() {
|
for p in 0..snd.len() {
|
||||||
let sample = snd.index(p);
|
let sample = snd.index(p);
|
||||||
out.write_all(&sample.to_le_bytes())?;
|
out.write_all(&sample.to_le_bytes())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
198
maraiah/text.rs
198
maraiah/text.rs
|
@ -11,45 +11,45 @@
|
||||||
/// ```
|
/// ```
|
||||||
pub fn to_binsize(n: u64) -> String
|
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
|
// empty size
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return String::from("empty");
|
return String::from("empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
// terabytes, gigabytes, megabytes, kilobytes
|
// terabytes, gigabytes, megabytes, kilobytes
|
||||||
for i in (1..=4).rev() {
|
for i in (1..=4).rev() {
|
||||||
let pow = 1000_u64.pow(i as u32);
|
let pow = 1000_u64.pow(i as u32);
|
||||||
if n >= pow {
|
if n >= pow {
|
||||||
return format!("{:1}{}", n / pow, NAMES[i - 1]);
|
return format!("{:1}{}", n / pow, NAMES[i - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// or, just bytes
|
// or, just bytes
|
||||||
format!("{} {}", n, if n == 1 {"byte"} else {"bytes"})
|
format!("{} {}", n, if n == 1 {"byte"} else {"bytes"})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encodes or decodes a string in the terminal encryption format.
|
/// Encodes or decodes a string in the terminal encryption format.
|
||||||
pub fn fuck_string(s: &[u8]) -> Vec<u8>
|
pub fn fuck_string(s: &[u8]) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut v = s.to_vec();
|
let mut v = s.to_vec();
|
||||||
let l = s.len();
|
let l = s.len();
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
for _ in 0..l / 4 {
|
for _ in 0..l / 4 {
|
||||||
p += 2;
|
p += 2;
|
||||||
v[p] ^= 0xfe;
|
v[p] ^= 0xfe;
|
||||||
v[p + 1] ^= 0xed;
|
v[p + 1] ^= 0xed;
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..l % 4 {
|
for _ in 0..l % 4 {
|
||||||
v[p] ^= 0xfe;
|
v[p] ^= 0xfe;
|
||||||
p += 1;
|
p += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a Pascal-style byte string with bounds checking.
|
/// 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]>
|
pub fn pascal_str(b: &[u8]) -> Option<&[u8]>
|
||||||
{
|
{
|
||||||
let s = usize::from(*b.get(0)?);
|
let s = usize::from(*b.get(0)?);
|
||||||
b.get(1..=s)
|
b.get(1..=s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts input from Mac Roman to a Unicode string.
|
/// 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
|
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() {
|
for &c in s.iter() {
|
||||||
let c = match c {
|
let c = match c {
|
||||||
0x80..=0xFF => TR[usize::from(c) & 0x7F],
|
0x80..=0xFF => TR[usize::from(c) & 0x7F],
|
||||||
b'\r' => '\n',
|
b'\r' => '\n',
|
||||||
c => char::from(c),
|
c => char::from(c),
|
||||||
};
|
};
|
||||||
|
|
||||||
v.push(c);
|
v.push(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a C-style string from Mac Roman to Unicode.
|
/// Converts a C-style string from Mac Roman to Unicode.
|
||||||
|
@ -110,11 +110,11 @@ pub fn mac_roman_conv(s: &[u8]) -> String
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mac_roman_cstr(s: &[u8]) -> String
|
pub fn mac_roman_cstr(s: &[u8]) -> String
|
||||||
{
|
{
|
||||||
if let Some(n) = memchr::memchr(0, s) {
|
if let Some(n) = memchr::memchr(0, s) {
|
||||||
mac_roman_conv(&s[..n])
|
mac_roman_conv(&s[..n])
|
||||||
} else {
|
} else {
|
||||||
mac_roman_conv(s)
|
mac_roman_conv(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts input from a Unicode string to Mac Roman.
|
/// 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>
|
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() {
|
for c in s.chars() {
|
||||||
let c = match c {
|
let c = match c {
|
||||||
'\n' => b'\r',
|
'\n' => b'\r',
|
||||||
'\0'..='\x7f' => c as u8,
|
'\0'..='\x7f' => c as u8,
|
||||||
c => {
|
c => {
|
||||||
if let Some(c) = TR.iter().position(|&o| o == c) {
|
if let Some(c) = TR.iter().position(|&o| o == c) {
|
||||||
c as u8 + 0x80
|
c as u8 + 0x80
|
||||||
} else {
|
} else {
|
||||||
0x7f
|
0x7f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
v.push(c);
|
v.push(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pads the output with zeroes.
|
/// 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>
|
pub fn pad_zero(mut v: Vec<u8>, n: usize) -> Vec<u8>
|
||||||
{
|
{
|
||||||
for _ in v.len()..n {
|
for _ in v.len()..n {
|
||||||
v.push(0);
|
v.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
const TR: [char; 128] =
|
const TR: [char; 128] =
|
||||||
['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}',
|
['\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{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
|
||||||
'\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}', '\u{00ea}', '\u{00eb}',
|
'\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{00ed}', '\u{00ec}', '\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}',
|
||||||
'\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}', '\u{00fa}', '\u{00f9}',
|
'\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{00fb}', '\u{00fc}', '\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}',
|
||||||
'\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}', '\u{00ae}', '\u{00a9}',
|
'\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{2122}', '\u{00b4}', '\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}',
|
||||||
'\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}', '\u{00a5}', '\u{00b5}',
|
'\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{2202}', '\u{2211}', '\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}',
|
||||||
'\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}', '\u{00bf}', '\u{00a1}',
|
'\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{00ac}', '\u{221a}', '\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}',
|
||||||
'\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}', '\u{00c3}', '\u{00d5}',
|
'\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{0152}', '\u{0153}', '\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}',
|
||||||
'\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}', '\u{00ff}', '\u{0178}',
|
'\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{2044}', '\u{20ac}', '\u{2039}', '\u{203a}', '\u{fb01}', '\u{fb02}',
|
||||||
'\u{2021}', '\u{00b7}', '\u{201a}', '\u{201e}', '\u{2030}', '\u{00c2}',
|
'\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{00ca}', '\u{00c1}', '\u{00cb}', '\u{00c8}', '\u{00cd}', '\u{00ce}',
|
||||||
'\u{00cf}', '\u{00cc}', '\u{00d3}', '\u{00d4}', '\u{f8ff}', '\u{00d2}',
|
'\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{00da}', '\u{00db}', '\u{00d9}', '\u{0131}', '\u{02c6}', '\u{02dc}',
|
||||||
'\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}', '\u{00b8}', '\u{02dd}',
|
'\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}', '\u{00b8}', '\u{02dd}',
|
||||||
'\u{02db}', '\u{02c7}'];
|
'\u{02db}', '\u{02c7}'];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_binsize_integrals()
|
fn to_binsize_integrals()
|
||||||
{
|
{
|
||||||
assert_eq!(to_binsize(0), "empty");
|
assert_eq!(to_binsize(0), "empty");
|
||||||
assert_eq!(to_binsize(1), "1 byte");
|
assert_eq!(to_binsize(1), "1 byte");
|
||||||
assert_eq!(to_binsize(2), "2 bytes");
|
assert_eq!(to_binsize(2), "2 bytes");
|
||||||
assert_eq!(to_binsize(999), "999 bytes");
|
assert_eq!(to_binsize(999), "999 bytes");
|
||||||
assert_eq!(to_binsize(1000), "1kB");
|
assert_eq!(to_binsize(1000), "1kB");
|
||||||
assert_eq!(to_binsize(1000 * 7), "7kB");
|
assert_eq!(to_binsize(1000 * 7), "7kB");
|
||||||
assert_eq!(to_binsize(1000 * 1000), "1MB");
|
assert_eq!(to_binsize(1000 * 1000), "1MB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
|
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
|
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 1000 * 7), "7GB");
|
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), "1TB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
|
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -2,37 +2,37 @@
|
||||||
|
|
||||||
impl Default for TransferMode
|
impl Default for TransferMode
|
||||||
{
|
{
|
||||||
fn default() -> Self {TransferMode::Normal}
|
fn default() -> Self {TransferMode::Normal}
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
/// A rendering style for many things.
|
/// A rendering style for many things.
|
||||||
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||||||
pub enum TransferMode: u16 {
|
pub enum TransferMode: u16 {
|
||||||
Normal = 0,
|
Normal = 0,
|
||||||
FadeBlack = 1,
|
FadeBlack = 1,
|
||||||
Invisibility = 2,
|
Invisibility = 2,
|
||||||
Invisibility2 = 3,
|
Invisibility2 = 3,
|
||||||
Pulsate = 4,
|
Pulsate = 4,
|
||||||
Wobble = 5,
|
Wobble = 5,
|
||||||
Wobble2 = 6,
|
Wobble2 = 6,
|
||||||
Static = 7,
|
Static = 7,
|
||||||
Static2 = 8,
|
Static2 = 8,
|
||||||
Sky = 9,
|
Sky = 9,
|
||||||
Smear = 10,
|
Smear = 10,
|
||||||
StaticFade = 11,
|
StaticFade = 11,
|
||||||
StaticPulse = 12,
|
StaticPulse = 12,
|
||||||
FoldIn = 13,
|
FoldIn = 13,
|
||||||
FoldOut = 14,
|
FoldOut = 14,
|
||||||
SlideHorz = 15,
|
SlideHorz = 15,
|
||||||
SlideHorz2 = 16,
|
SlideHorz2 = 16,
|
||||||
SlideVert = 17,
|
SlideVert = 17,
|
||||||
SlideVert2 = 18,
|
SlideVert2 = 18,
|
||||||
Wander = 19,
|
Wander = 19,
|
||||||
Wander2 = 20,
|
Wander2 = 20,
|
||||||
BigSky = 21,
|
BigSky = 21,
|
||||||
None = 0xFFFF,
|
None = 0xFFFF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// 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(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(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(5120)},
|
||||||
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(6144)},
|
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(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(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(6144)},
|
||||||
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(5120)},
|
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(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(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(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(4608)},
|
||||||
map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(6656)},
|
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(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(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(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(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(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(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(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(1536)},
|
||||||
map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(9728)},
|
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(1536)},
|
||||||
map::pnts::Point{x: Unit::from_bits(63488), y: Unit::from_bits(9728)},
|
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(13312)},
|
||||||
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(14336)},
|
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(13312)},
|
||||||
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(14336)},
|
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(63488)},
|
||||||
map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(62464)},
|
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(62464)},
|
||||||
map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(61440)},
|
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(61440)},
|
||||||
map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(62464)},
|
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(62464)},
|
||||||
map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(63488)},
|
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(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(5120)},
|
||||||
map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(6144)},
|
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(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(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(5120)},
|
||||||
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(4096)},
|
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(4096)},
|
||||||
map::pnts::Point{x: Unit::from_bits(61440), y: Unit::from_bits(7168)},
|
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(7168)},
|
||||||
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(6144)},
|
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(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(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(7680)},
|
||||||
map::pnts::Point{x: Unit::from_bits(62464), y: Unit::from_bits(13312)},
|
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(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(8704)},
|
||||||
map::pnts::Point{x: Unit::from_bits(57344), y: Unit::from_bits(13312)}
|
map::pnts::Point{x: Unit::from_bits(57344), y: Unit::from_bits(13312)}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,434 +1,434 @@
|
||||||
[
|
[
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(4096)},
|
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(4096)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(4096)},
|
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(4096)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(5120)},
|
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(5120)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(6144)},
|
pos: map::pnts::Point{x: Unit::from_bits(7168), y: Unit::from_bits(6144)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(7168)},
|
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(7168)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(7168)},
|
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(7168)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(6144)},
|
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(6144)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(5120)},
|
pos: map::pnts::Point{x: Unit::from_bits(4096), y: Unit::from_bits(5120)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(3072)},
|
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(3072)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(4608)},
|
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(4608)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(3072)},
|
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(3072)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(4608)},
|
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(4608)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(6656)},
|
pos: map::pnts::Point{x: Unit::from_bits(8192), y: Unit::from_bits(6656)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(8192)},
|
pos: map::pnts::Point{x: Unit::from_bits(6656), y: Unit::from_bits(8192)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(8192)},
|
pos: map::pnts::Point{x: Unit::from_bits(4608), y: Unit::from_bits(8192)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
flags: map::epnt::EndpointFlags::SAME_HEIGHT |
|
||||||
map::epnt::EndpointFlags::TRANSPARENT,
|
map::epnt::EndpointFlags::TRANSPARENT,
|
||||||
hei_hi: Unit::from_bits(0),
|
hei_hi: Unit::from_bits(0),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(6656)},
|
pos: map::pnts::Point{x: Unit::from_bits(3072), y: Unit::from_bits(6656)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(13312)},
|
pos: map::pnts::Point{x: Unit::from_bits(1536), y: Unit::from_bits(13312)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(13312)},
|
pos: map::pnts::Point{x: Unit::from_bits(9728), y: Unit::from_bits(13312)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(1536), y: -Unit::from_bits(2048)},
|
pos: map::pnts::Point{x: Unit::from_bits(1536), y: -Unit::from_bits(2048)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(9728), y: -Unit::from_bits(2048)},
|
pos: map::pnts::Point{x: Unit::from_bits(9728), y: -Unit::from_bits(2048)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(1536)},
|
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(1536)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(9728)},
|
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(9728)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(1536)},
|
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(1536)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: Unit::from_bits(9216),
|
hei_lo: Unit::from_bits(9216),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(9728)},
|
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(9728)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(13312)},
|
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(13312)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(14336)},
|
pos: map::pnts::Point{x: Unit::from_bits(5120), y: Unit::from_bits(14336)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(13312)},
|
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(13312)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(14336)},
|
pos: map::pnts::Point{x: Unit::from_bits(6144), y: Unit::from_bits(14336)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(2048)},
|
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(2048)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(3072)},
|
pos: map::pnts::Point{x: Unit::from_bits(5120), y: -Unit::from_bits(3072)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(3072)},
|
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(3072)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(4096)},
|
pos: map::pnts::Point{x: Unit::from_bits(4096), y: -Unit::from_bits(4096)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(4096)},
|
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(4096)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(3072)},
|
pos: map::pnts::Point{x: Unit::from_bits(7168), y: -Unit::from_bits(3072)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(3072)},
|
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(3072)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(2048)},
|
pos: map::pnts::Point{x: Unit::from_bits(6144), y: -Unit::from_bits(2048)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(5120)},
|
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(5120)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(5120)},
|
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(5120)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(6144)},
|
pos: map::pnts::Point{x: Unit::from_bits(14336), y: Unit::from_bits(6144)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: -Unit::from_bits(9216),
|
hei_hi: -Unit::from_bits(9216),
|
||||||
hei_lo: -Unit::from_bits(8192),
|
hei_lo: -Unit::from_bits(8192),
|
||||||
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(6144)},
|
pos: map::pnts::Point{x: Unit::from_bits(13312), y: Unit::from_bits(6144)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(5120)},
|
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(5120)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(5120)},
|
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(5120)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(4096)},
|
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(4096)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(4096)},
|
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(4096)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(1024),
|
hei_lo: Unit::from_bits(1024),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7168)},
|
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7168)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(1024),
|
hei_lo: Unit::from_bits(1024),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7168)},
|
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7168)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(6144)},
|
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(6144)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(6144)},
|
pos: map::pnts::Point{x: -Unit::from_bits(2048), y: Unit::from_bits(6144)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(1024),
|
hei_lo: Unit::from_bits(1024),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7680)},
|
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(7680)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(1024),
|
hei_lo: Unit::from_bits(1024),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7680)},
|
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(7680)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(13312)},
|
pos: map::pnts::Point{x: -Unit::from_bits(3072), y: Unit::from_bits(13312)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(8704)},
|
pos: map::pnts::Point{x: -Unit::from_bits(4096), y: Unit::from_bits(8704)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(8704)},
|
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(8704)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
map::epnt::Endpoint{
|
map::epnt::Endpoint{
|
||||||
flags: map::epnt::EndpointFlags::SOLID |
|
flags: map::epnt::EndpointFlags::SOLID |
|
||||||
map::epnt::EndpointFlags::SAME_HEIGHT,
|
map::epnt::EndpointFlags::SAME_HEIGHT,
|
||||||
hei_hi: Unit::from_bits(1024),
|
hei_hi: Unit::from_bits(1024),
|
||||||
hei_lo: Unit::from_bits(2047),
|
hei_lo: Unit::from_bits(2047),
|
||||||
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(13312)},
|
pos: map::pnts::Point{x: -Unit::from_bits(8192), y: Unit::from_bits(13312)},
|
||||||
support: 0
|
support: 0
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
map::minf::Info{
|
map::minf::Info{
|
||||||
texture_id: 0,
|
texture_id: 0,
|
||||||
physics_id: 1,
|
physics_id: 1,
|
||||||
skypict_id: 1,
|
skypict_id: 1,
|
||||||
miss_flags: map::minf::MissionFlags::REPAIR,
|
miss_flags: map::minf::MissionFlags::REPAIR,
|
||||||
envi_flags: map::minf::EnvironmentFlags::empty(),
|
envi_flags: map::minf::EnvironmentFlags::empty(),
|
||||||
entr_flags: map::minf::EntryFlags::SOLO | map::minf::EntryFlags::CO_OP,
|
entr_flags: map::minf::EntryFlags::SOLO | map::minf::EntryFlags::CO_OP,
|
||||||
level_name: "Waterloo Waterpark".to_owned()
|
level_name: "Waterloo Waterpark".to_owned()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,146 +1,146 @@
|
||||||
vec![
|
vec![
|
||||||
map::term::Terminal {
|
map::term::Terminal {
|
||||||
lines: 22,
|
lines: 22,
|
||||||
groups: vec![
|
groups: vec![
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Unfinished,
|
ttype: map::trmg::GroupType::Unfinished,
|
||||||
lines: 0,
|
lines: 0,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logon(1600),
|
ttype: map::trmg::GroupType::Logon(1600),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "\n".to_owned()
|
text: "\n".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Pict(10011),
|
ttype: map::trmg::GroupType::Pict(10011),
|
||||||
lines: 22,
|
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()
|
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 {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Pict(10005),
|
ttype: map::trmg::GroupType::Pict(10005),
|
||||||
lines: 21,
|
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()
|
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 {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Pict(10006),
|
ttype: map::trmg::GroupType::Pict(10006),
|
||||||
lines: 21,
|
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()
|
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 {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logoff(1600),
|
ttype: map::trmg::GroupType::Logoff(1600),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "\n".to_owned()
|
text: "\n".to_owned()
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
faces: vec![]
|
faces: vec![]
|
||||||
},
|
},
|
||||||
map::term::Terminal {
|
map::term::Terminal {
|
||||||
lines: 22,
|
lines: 22,
|
||||||
groups: vec![
|
groups: vec![
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Unfinished,
|
ttype: map::trmg::GroupType::Unfinished,
|
||||||
lines: 0,
|
lines: 0,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logon(1610),
|
ttype: map::trmg::GroupType::Logon(1610),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "\n".to_owned()
|
text: "\n".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Pict(10008),
|
ttype: map::trmg::GroupType::Pict(10008),
|
||||||
lines: 14,
|
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()
|
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 {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logoff(1610),
|
ttype: map::trmg::GroupType::Logoff(1610),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "\n".to_owned()
|
text: "\n".to_owned()
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
faces: vec![]
|
faces: vec![]
|
||||||
},
|
},
|
||||||
map::term::Terminal {
|
map::term::Terminal {
|
||||||
lines: 22,
|
lines: 22,
|
||||||
groups: vec![
|
groups: vec![
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Unfinished,
|
ttype: map::trmg::GroupType::Unfinished,
|
||||||
lines: 0,
|
lines: 0,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logon(1619),
|
ttype: map::trmg::GroupType::Logon(1619),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Pict(10007),
|
ttype: map::trmg::GroupType::Pict(10007),
|
||||||
lines: 16,
|
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()
|
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 {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logoff(1619),
|
ttype: map::trmg::GroupType::Logoff(1619),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::TeleInter(1),
|
ttype: map::trmg::GroupType::TeleInter(1),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
faces: vec![
|
faces: vec![
|
||||||
map::trmf::Face {
|
map::trmf::Face {
|
||||||
start: 6,
|
start: 6,
|
||||||
face: 0,
|
face: 0,
|
||||||
color: 1
|
color: 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
map::term::Terminal {
|
map::term::Terminal {
|
||||||
lines: 22,
|
lines: 22,
|
||||||
groups: vec![
|
groups: vec![
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Unfinished,
|
ttype: map::trmg::GroupType::Unfinished,
|
||||||
lines: 0,
|
lines: 0,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logon(1619),
|
ttype: map::trmg::GroupType::Logon(1619),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
},
|
},
|
||||||
map::trmg::Group {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Pict(10007),
|
ttype: map::trmg::GroupType::Pict(10007),
|
||||||
lines: 84,
|
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()
|
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 {
|
map::trmg::Group {
|
||||||
flags: map::trmg::GroupFlags::empty(),
|
flags: map::trmg::GroupFlags::empty(),
|
||||||
ttype: map::trmg::GroupType::Logoff(1619),
|
ttype: map::trmg::GroupType::Logoff(1619),
|
||||||
lines: 1,
|
lines: 1,
|
||||||
text: "".to_owned()
|
text: "".to_owned()
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
faces: vec![]
|
faces: vec![]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,258 +1,258 @@
|
||||||
[
|
[
|
||||||
Color8::new(255, 255, 255),
|
Color8::new(255, 255, 255),
|
||||||
Color8::new(7, 9, 19 ),
|
Color8::new(7, 9, 19 ),
|
||||||
Color8::new(7, 18, 42 ),
|
Color8::new(7, 18, 42 ),
|
||||||
Color8::new(61, 66, 20 ),
|
Color8::new(61, 66, 20 ),
|
||||||
Color8::new(39, 12, 18 ),
|
Color8::new(39, 12, 18 ),
|
||||||
Color8::new(28, 35, 47 ),
|
Color8::new(28, 35, 47 ),
|
||||||
Color8::new(52, 52, 62 ),
|
Color8::new(52, 52, 62 ),
|
||||||
Color8::new(14, 5, 6 ),
|
Color8::new(14, 5, 6 ),
|
||||||
Color8::new(48, 61, 79 ),
|
Color8::new(48, 61, 79 ),
|
||||||
Color8::new(44, 21, 32 ),
|
Color8::new(44, 21, 32 ),
|
||||||
Color8::new(220, 220, 1 ),
|
Color8::new(220, 220, 1 ),
|
||||||
Color8::new(16, 19, 28 ),
|
Color8::new(16, 19, 28 ),
|
||||||
Color8::new(29, 41, 59 ),
|
Color8::new(29, 41, 59 ),
|
||||||
Color8::new(70, 82, 94 ),
|
Color8::new(70, 82, 94 ),
|
||||||
Color8::new(240, 241, 242),
|
Color8::new(240, 241, 242),
|
||||||
Color8::new(138, 141, 149),
|
Color8::new(138, 141, 149),
|
||||||
Color8::new(211, 212, 213),
|
Color8::new(211, 212, 213),
|
||||||
Color8::new(130, 129, 132),
|
Color8::new(130, 129, 132),
|
||||||
Color8::new(73, 74, 82 ),
|
Color8::new(73, 74, 82 ),
|
||||||
Color8::new(94, 97, 102),
|
Color8::new(94, 97, 102),
|
||||||
Color8::new(28, 23, 40 ),
|
Color8::new(28, 23, 40 ),
|
||||||
Color8::new(72, 52, 61 ),
|
Color8::new(72, 52, 61 ),
|
||||||
Color8::new(149, 151, 156),
|
Color8::new(149, 151, 156),
|
||||||
Color8::new(85, 83, 2 ),
|
Color8::new(85, 83, 2 ),
|
||||||
Color8::new(111, 111, 3 ),
|
Color8::new(111, 111, 3 ),
|
||||||
Color8::new(224, 225, 225),
|
Color8::new(224, 225, 225),
|
||||||
Color8::new(52, 26, 39 ),
|
Color8::new(52, 26, 39 ),
|
||||||
Color8::new(57, 18, 19 ),
|
Color8::new(57, 18, 19 ),
|
||||||
Color8::new(97, 98, 3 ),
|
Color8::new(97, 98, 3 ),
|
||||||
Color8::new(23, 10, 17 ),
|
Color8::new(23, 10, 17 ),
|
||||||
Color8::new(137, 137, 1 ),
|
Color8::new(137, 137, 1 ),
|
||||||
Color8::new(56, 55, 1 ),
|
Color8::new(56, 55, 1 ),
|
||||||
Color8::new(194, 193, 3 ),
|
Color8::new(194, 193, 3 ),
|
||||||
Color8::new(160, 160, 160),
|
Color8::new(160, 160, 160),
|
||||||
Color8::new(173, 172, 11 ),
|
Color8::new(173, 172, 11 ),
|
||||||
Color8::new(151, 155, 24 ),
|
Color8::new(151, 155, 24 ),
|
||||||
Color8::new(195, 193, 194),
|
Color8::new(195, 193, 194),
|
||||||
Color8::new(41, 49, 73 ),
|
Color8::new(41, 49, 73 ),
|
||||||
Color8::new(202, 203, 205),
|
Color8::new(202, 203, 205),
|
||||||
Color8::new(137, 126, 21 ),
|
Color8::new(137, 126, 21 ),
|
||||||
Color8::new(123, 122, 17 ),
|
Color8::new(123, 122, 17 ),
|
||||||
Color8::new(71, 75, 28 ),
|
Color8::new(71, 75, 28 ),
|
||||||
Color8::new(66, 63, 64 ),
|
Color8::new(66, 63, 64 ),
|
||||||
Color8::new(30, 30, 6 ),
|
Color8::new(30, 30, 6 ),
|
||||||
Color8::new(166, 166, 6 ),
|
Color8::new(166, 166, 6 ),
|
||||||
Color8::new(64, 39, 48 ),
|
Color8::new(64, 39, 48 ),
|
||||||
Color8::new(46, 33, 41 ),
|
Color8::new(46, 33, 41 ),
|
||||||
Color8::new(56, 37, 77 ),
|
Color8::new(56, 37, 77 ),
|
||||||
Color8::new(50, 41, 51 ),
|
Color8::new(50, 41, 51 ),
|
||||||
Color8::new(111, 112, 116),
|
Color8::new(111, 112, 116),
|
||||||
Color8::new(110, 117, 63 ),
|
Color8::new(110, 117, 63 ),
|
||||||
Color8::new(72, 25, 29 ),
|
Color8::new(72, 25, 29 ),
|
||||||
Color8::new(98, 105, 85 ),
|
Color8::new(98, 105, 85 ),
|
||||||
Color8::new(71, 60, 5 ),
|
Color8::new(71, 60, 5 ),
|
||||||
Color8::new(185, 183, 6 ),
|
Color8::new(185, 183, 6 ),
|
||||||
Color8::new(31, 15, 24 ),
|
Color8::new(31, 15, 24 ),
|
||||||
Color8::new(150, 154, 48 ),
|
Color8::new(150, 154, 48 ),
|
||||||
Color8::new(45, 41, 7 ),
|
Color8::new(45, 41, 7 ),
|
||||||
Color8::new(84, 92, 103),
|
Color8::new(84, 92, 103),
|
||||||
Color8::new(124, 129, 26 ),
|
Color8::new(124, 129, 26 ),
|
||||||
Color8::new(35, 29, 61 ),
|
Color8::new(35, 29, 61 ),
|
||||||
Color8::new(57, 70, 87 ),
|
Color8::new(57, 70, 87 ),
|
||||||
Color8::new(116, 119, 130),
|
Color8::new(116, 119, 130),
|
||||||
Color8::new(51, 45, 26 ),
|
Color8::new(51, 45, 26 ),
|
||||||
Color8::new(69, 62, 95 ),
|
Color8::new(69, 62, 95 ),
|
||||||
Color8::new(86, 90, 43 ),
|
Color8::new(86, 90, 43 ),
|
||||||
Color8::new(125, 119, 5 ),
|
Color8::new(125, 119, 5 ),
|
||||||
Color8::new(95, 99, 25 ),
|
Color8::new(95, 99, 25 ),
|
||||||
Color8::new(135, 135, 139),
|
Color8::new(135, 135, 139),
|
||||||
Color8::new(54, 61, 34 ),
|
Color8::new(54, 61, 34 ),
|
||||||
Color8::new(66, 71, 36 ),
|
Color8::new(66, 71, 36 ),
|
||||||
Color8::new(144, 145, 12 ),
|
Color8::new(144, 145, 12 ),
|
||||||
Color8::new(87, 71, 23 ),
|
Color8::new(87, 71, 23 ),
|
||||||
Color8::new(163, 168, 35 ),
|
Color8::new(163, 168, 35 ),
|
||||||
Color8::new(206, 207, 3 ),
|
Color8::new(206, 207, 3 ),
|
||||||
Color8::new(186, 189, 23 ),
|
Color8::new(186, 189, 23 ),
|
||||||
Color8::new(97, 96, 49 ),
|
Color8::new(97, 96, 49 ),
|
||||||
Color8::new(29, 42, 32 ),
|
Color8::new(29, 42, 32 ),
|
||||||
Color8::new(136, 141, 36 ),
|
Color8::new(136, 141, 36 ),
|
||||||
Color8::new(96, 104, 115),
|
Color8::new(96, 104, 115),
|
||||||
Color8::new(110, 115, 26 ),
|
Color8::new(110, 115, 26 ),
|
||||||
Color8::new(113, 81, 82 ),
|
Color8::new(113, 81, 82 ),
|
||||||
Color8::new(88, 71, 71 ),
|
Color8::new(88, 71, 71 ),
|
||||||
Color8::new(83, 46, 47 ),
|
Color8::new(83, 46, 47 ),
|
||||||
Color8::new(87, 89, 15 ),
|
Color8::new(87, 89, 15 ),
|
||||||
Color8::new(172, 176, 181),
|
Color8::new(172, 176, 181),
|
||||||
Color8::new(91, 77, 84 ),
|
Color8::new(91, 77, 84 ),
|
||||||
Color8::new(231, 232, 235),
|
Color8::new(231, 232, 235),
|
||||||
Color8::new(255, 127, 255),
|
Color8::new(255, 127, 255),
|
||||||
Color8::new(4, 3, 4 ),
|
Color8::new(4, 3, 4 ),
|
||||||
Color8::new(4, 9, 21 ),
|
Color8::new(4, 9, 21 ),
|
||||||
Color8::new(1, 4, 10 ),
|
Color8::new(1, 4, 10 ),
|
||||||
Color8::new(1, 2, 3 ),
|
Color8::new(1, 2, 3 ),
|
||||||
Color8::new(141, 144, 16 ),
|
Color8::new(141, 144, 16 ),
|
||||||
Color8::new(1, 0, 0 ),
|
Color8::new(1, 0, 0 ),
|
||||||
Color8::new(25, 30, 40 ),
|
Color8::new(25, 30, 40 ),
|
||||||
Color8::new(14, 17, 27 ),
|
Color8::new(14, 17, 27 ),
|
||||||
Color8::new(152, 155, 162),
|
Color8::new(152, 155, 162),
|
||||||
Color8::new(0, 3, 7 ),
|
Color8::new(0, 3, 7 ),
|
||||||
Color8::new(27, 33, 43 ),
|
Color8::new(27, 33, 43 ),
|
||||||
Color8::new(4, 4, 7 ),
|
Color8::new(4, 4, 7 ),
|
||||||
Color8::new(5, 1, 2 ),
|
Color8::new(5, 1, 2 ),
|
||||||
Color8::new(3, 12, 32 ),
|
Color8::new(3, 12, 32 ),
|
||||||
Color8::new(0, 0, 1 ),
|
Color8::new(0, 0, 1 ),
|
||||||
Color8::new(17, 17, 19 ),
|
Color8::new(17, 17, 19 ),
|
||||||
Color8::new(69, 66, 71 ),
|
Color8::new(69, 66, 71 ),
|
||||||
Color8::new(0, 1, 5 ),
|
Color8::new(0, 1, 5 ),
|
||||||
Color8::new(6, 7, 15 ),
|
Color8::new(6, 7, 15 ),
|
||||||
Color8::new(1, 0, 2 ),
|
Color8::new(1, 0, 2 ),
|
||||||
Color8::new(3, 2, 8 ),
|
Color8::new(3, 2, 8 ),
|
||||||
Color8::new(0, 1, 1 ),
|
Color8::new(0, 1, 1 ),
|
||||||
Color8::new(20, 25, 36 ),
|
Color8::new(20, 25, 36 ),
|
||||||
Color8::new(24, 7, 10 ),
|
Color8::new(24, 7, 10 ),
|
||||||
Color8::new(7, 8, 18 ),
|
Color8::new(7, 8, 18 ),
|
||||||
Color8::new(32, 46, 65 ),
|
Color8::new(32, 46, 65 ),
|
||||||
Color8::new(17, 15, 29 ),
|
Color8::new(17, 15, 29 ),
|
||||||
Color8::new(10, 12, 23 ),
|
Color8::new(10, 12, 23 ),
|
||||||
Color8::new(6, 10, 23 ),
|
Color8::new(6, 10, 23 ),
|
||||||
Color8::new(23, 16, 25 ),
|
Color8::new(23, 16, 25 ),
|
||||||
Color8::new(0, 1, 2 ),
|
Color8::new(0, 1, 2 ),
|
||||||
Color8::new(1, 6, 15 ),
|
Color8::new(1, 6, 15 ),
|
||||||
Color8::new(3, 4, 12 ),
|
Color8::new(3, 4, 12 ),
|
||||||
Color8::new(1, 1, 2 ),
|
Color8::new(1, 1, 2 ),
|
||||||
Color8::new(66, 75, 87 ),
|
Color8::new(66, 75, 87 ),
|
||||||
Color8::new(161, 163, 170),
|
Color8::new(161, 163, 170),
|
||||||
Color8::new(20, 6, 6 ),
|
Color8::new(20, 6, 6 ),
|
||||||
Color8::new(1, 2, 8 ),
|
Color8::new(1, 2, 8 ),
|
||||||
Color8::new(2, 4, 8 ),
|
Color8::new(2, 4, 8 ),
|
||||||
Color8::new(6, 7, 16 ),
|
Color8::new(6, 7, 16 ),
|
||||||
Color8::new(2, 5, 13 ),
|
Color8::new(2, 5, 13 ),
|
||||||
Color8::new(1, 13, 32 ),
|
Color8::new(1, 13, 32 ),
|
||||||
Color8::new(17, 22, 35 ),
|
Color8::new(17, 22, 35 ),
|
||||||
Color8::new(0, 0, 4 ),
|
Color8::new(0, 0, 4 ),
|
||||||
Color8::new(39, 24, 37 ),
|
Color8::new(39, 24, 37 ),
|
||||||
Color8::new(24, 35, 56 ),
|
Color8::new(24, 35, 56 ),
|
||||||
Color8::new(5, 4, 11 ),
|
Color8::new(5, 4, 11 ),
|
||||||
Color8::new(5, 6, 15 ),
|
Color8::new(5, 6, 15 ),
|
||||||
Color8::new(5, 10, 27 ),
|
Color8::new(5, 10, 27 ),
|
||||||
Color8::new(2, 5, 10 ),
|
Color8::new(2, 5, 10 ),
|
||||||
Color8::new(37, 50, 69 ),
|
Color8::new(37, 50, 69 ),
|
||||||
Color8::new(1, 4, 14 ),
|
Color8::new(1, 4, 14 ),
|
||||||
Color8::new(1, 1, 1 ),
|
Color8::new(1, 1, 1 ),
|
||||||
Color8::new(16, 24, 48 ),
|
Color8::new(16, 24, 48 ),
|
||||||
Color8::new(2, 1, 4 ),
|
Color8::new(2, 1, 4 ),
|
||||||
Color8::new(14, 19, 40 ),
|
Color8::new(14, 19, 40 ),
|
||||||
Color8::new(0, 5, 12 ),
|
Color8::new(0, 5, 12 ),
|
||||||
Color8::new(0, 1, 4 ),
|
Color8::new(0, 1, 4 ),
|
||||||
Color8::new(7, 3, 3 ),
|
Color8::new(7, 3, 3 ),
|
||||||
Color8::new(41, 55, 71 ),
|
Color8::new(41, 55, 71 ),
|
||||||
Color8::new(2, 0, 0 ),
|
Color8::new(2, 0, 0 ),
|
||||||
Color8::new(35, 11, 11 ),
|
Color8::new(35, 11, 11 ),
|
||||||
Color8::new(11, 14, 27 ),
|
Color8::new(11, 14, 27 ),
|
||||||
Color8::new(0, 1, 3 ),
|
Color8::new(0, 1, 3 ),
|
||||||
Color8::new(1, 13, 30 ),
|
Color8::new(1, 13, 30 ),
|
||||||
Color8::new(6, 18, 39 ),
|
Color8::new(6, 18, 39 ),
|
||||||
Color8::new(196, 196, 7 ),
|
Color8::new(196, 196, 7 ),
|
||||||
Color8::new(1, 1, 7 ),
|
Color8::new(1, 1, 7 ),
|
||||||
Color8::new(2, 11, 28 ),
|
Color8::new(2, 11, 28 ),
|
||||||
Color8::new(3, 1, 3 ),
|
Color8::new(3, 1, 3 ),
|
||||||
Color8::new(5, 17, 39 ),
|
Color8::new(5, 17, 39 ),
|
||||||
Color8::new(4, 6, 14 ),
|
Color8::new(4, 6, 14 ),
|
||||||
Color8::new(19, 17, 36 ),
|
Color8::new(19, 17, 36 ),
|
||||||
Color8::new(2, 7, 15 ),
|
Color8::new(2, 7, 15 ),
|
||||||
Color8::new(0, 3, 8 ),
|
Color8::new(0, 3, 8 ),
|
||||||
Color8::new(13, 10, 19 ),
|
Color8::new(13, 10, 19 ),
|
||||||
Color8::new(143, 149, 157),
|
Color8::new(143, 149, 157),
|
||||||
Color8::new(10, 4, 5 ),
|
Color8::new(10, 4, 5 ),
|
||||||
Color8::new(8, 6, 14 ),
|
Color8::new(8, 6, 14 ),
|
||||||
Color8::new(32, 21, 35 ),
|
Color8::new(32, 21, 35 ),
|
||||||
Color8::new(17, 7, 13 ),
|
Color8::new(17, 7, 13 ),
|
||||||
Color8::new(45, 56, 79 ),
|
Color8::new(45, 56, 79 ),
|
||||||
Color8::new(3, 10, 25 ),
|
Color8::new(3, 10, 25 ),
|
||||||
Color8::new(2, 3, 6 ),
|
Color8::new(2, 3, 6 ),
|
||||||
Color8::new(34, 42, 68 ),
|
Color8::new(34, 42, 68 ),
|
||||||
Color8::new(2, 15, 34 ),
|
Color8::new(2, 15, 34 ),
|
||||||
Color8::new(10, 21, 43 ),
|
Color8::new(10, 21, 43 ),
|
||||||
Color8::new(0, 2, 5 ),
|
Color8::new(0, 2, 5 ),
|
||||||
Color8::new(15, 17, 27 ),
|
Color8::new(15, 17, 27 ),
|
||||||
Color8::new(7, 3, 6 ),
|
Color8::new(7, 3, 6 ),
|
||||||
Color8::new(2, 10, 23 ),
|
Color8::new(2, 10, 23 ),
|
||||||
Color8::new(22, 19, 32 ),
|
Color8::new(22, 19, 32 ),
|
||||||
Color8::new(58, 59, 7 ),
|
Color8::new(58, 59, 7 ),
|
||||||
Color8::new(8, 3, 9 ),
|
Color8::new(8, 3, 9 ),
|
||||||
Color8::new(6, 3, 8 ),
|
Color8::new(6, 3, 8 ),
|
||||||
Color8::new(4, 14, 30 ),
|
Color8::new(4, 14, 30 ),
|
||||||
Color8::new(2, 2, 4 ),
|
Color8::new(2, 2, 4 ),
|
||||||
Color8::new(0, 3, 9 ),
|
Color8::new(0, 3, 9 ),
|
||||||
Color8::new(51, 64, 82 ),
|
Color8::new(51, 64, 82 ),
|
||||||
Color8::new(2, 3, 10 ),
|
Color8::new(2, 3, 10 ),
|
||||||
Color8::new(4, 12, 29 ),
|
Color8::new(4, 12, 29 ),
|
||||||
Color8::new(18, 22, 31 ),
|
Color8::new(18, 22, 31 ),
|
||||||
Color8::new(2, 4, 13 ),
|
Color8::new(2, 4, 13 ),
|
||||||
Color8::new(192, 192, 193),
|
Color8::new(192, 192, 193),
|
||||||
Color8::new(3, 0, 0 ),
|
Color8::new(3, 0, 0 ),
|
||||||
Color8::new(5, 6, 14 ),
|
Color8::new(5, 6, 14 ),
|
||||||
Color8::new(2, 2, 9 ),
|
Color8::new(2, 2, 9 ),
|
||||||
Color8::new(51, 63, 74 ),
|
Color8::new(51, 63, 74 ),
|
||||||
Color8::new(13, 16, 33 ),
|
Color8::new(13, 16, 33 ),
|
||||||
Color8::new(5, 8, 19 ),
|
Color8::new(5, 8, 19 ),
|
||||||
Color8::new(23, 27, 38 ),
|
Color8::new(23, 27, 38 ),
|
||||||
Color8::new(23, 28, 54 ),
|
Color8::new(23, 28, 54 ),
|
||||||
Color8::new(1, 4, 11 ),
|
Color8::new(1, 4, 11 ),
|
||||||
Color8::new(33, 40, 49 ),
|
Color8::new(33, 40, 49 ),
|
||||||
Color8::new(48, 59, 71 ),
|
Color8::new(48, 59, 71 ),
|
||||||
Color8::new(64, 26, 36 ),
|
Color8::new(64, 26, 36 ),
|
||||||
Color8::new(116, 121, 19 ),
|
Color8::new(116, 121, 19 ),
|
||||||
Color8::new(13, 16, 26 ),
|
Color8::new(13, 16, 26 ),
|
||||||
Color8::new(3, 6, 11 ),
|
Color8::new(3, 6, 11 ),
|
||||||
Color8::new(5, 2, 2 ),
|
Color8::new(5, 2, 2 ),
|
||||||
Color8::new(7, 9, 18 ),
|
Color8::new(7, 9, 18 ),
|
||||||
Color8::new(11, 7, 16 ),
|
Color8::new(11, 7, 16 ),
|
||||||
Color8::new(0, 2, 6 ),
|
Color8::new(0, 2, 6 ),
|
||||||
Color8::new(3, 3, 3 ),
|
Color8::new(3, 3, 3 ),
|
||||||
Color8::new(2, 6, 16 ),
|
Color8::new(2, 6, 16 ),
|
||||||
Color8::new(13, 12, 13 ),
|
Color8::new(13, 12, 13 ),
|
||||||
Color8::new(6, 8, 18 ),
|
Color8::new(6, 8, 18 ),
|
||||||
Color8::new(1, 11, 25 ),
|
Color8::new(1, 11, 25 ),
|
||||||
Color8::new(18, 13, 24 ),
|
Color8::new(18, 13, 24 ),
|
||||||
Color8::new(1, 0, 1 ),
|
Color8::new(1, 0, 1 ),
|
||||||
Color8::new(0, 0, 3 ),
|
Color8::new(0, 0, 3 ),
|
||||||
Color8::new(20, 27, 41 ),
|
Color8::new(20, 27, 41 ),
|
||||||
Color8::new(7, 15, 35 ),
|
Color8::new(7, 15, 35 ),
|
||||||
Color8::new(129, 135, 145),
|
Color8::new(129, 135, 145),
|
||||||
Color8::new(1, 11, 26 ),
|
Color8::new(1, 11, 26 ),
|
||||||
Color8::new(9, 10, 20 ),
|
Color8::new(9, 10, 20 ),
|
||||||
Color8::new(1, 2, 4 ),
|
Color8::new(1, 2, 4 ),
|
||||||
Color8::new(5, 5, 15 ),
|
Color8::new(5, 5, 15 ),
|
||||||
Color8::new(8, 9, 9 ),
|
Color8::new(8, 9, 9 ),
|
||||||
Color8::new(16, 6, 10 ),
|
Color8::new(16, 6, 10 ),
|
||||||
Color8::new(7, 6, 17 ),
|
Color8::new(7, 6, 17 ),
|
||||||
Color8::new(33, 41, 28 ),
|
Color8::new(33, 41, 28 ),
|
||||||
Color8::new(15, 19, 31 ),
|
Color8::new(15, 19, 31 ),
|
||||||
Color8::new(2, 1, 1 ),
|
Color8::new(2, 1, 1 ),
|
||||||
Color8::new(13, 13, 24 ),
|
Color8::new(13, 13, 24 ),
|
||||||
Color8::new(59, 70, 81 ),
|
Color8::new(59, 70, 81 ),
|
||||||
Color8::new(33, 33, 39 ),
|
Color8::new(33, 33, 39 ),
|
||||||
Color8::new(1, 8, 18 ),
|
Color8::new(1, 8, 18 ),
|
||||||
Color8::new(8, 10, 20 ),
|
Color8::new(8, 10, 20 ),
|
||||||
Color8::new(3, 5, 16 ),
|
Color8::new(3, 5, 16 ),
|
||||||
Color8::new(114, 116, 10 ),
|
Color8::new(114, 116, 10 ),
|
||||||
Color8::new(23, 32, 47 ),
|
Color8::new(23, 32, 47 ),
|
||||||
Color8::new(147, 145, 150),
|
Color8::new(147, 145, 150),
|
||||||
Color8::new(2, 8, 20 ),
|
Color8::new(2, 8, 20 ),
|
||||||
Color8::new(1, 5, 11 ),
|
Color8::new(1, 5, 11 ),
|
||||||
Color8::new(42, 52, 63 ),
|
Color8::new(42, 52, 63 ),
|
||||||
Color8::new(13, 6, 11 ),
|
Color8::new(13, 6, 11 ),
|
||||||
Color8::new(79, 83, 93 ),
|
Color8::new(79, 83, 93 ),
|
||||||
Color8::new(195, 195, 198),
|
Color8::new(195, 195, 198),
|
||||||
Color8::new(66, 21, 24 ),
|
Color8::new(66, 21, 24 ),
|
||||||
Color8::new(7, 13, 29 ),
|
Color8::new(7, 13, 29 ),
|
||||||
Color8::new(11, 14, 23 ),
|
Color8::new(11, 14, 23 ),
|
||||||
Color8::new(12, 5, 8 ),
|
Color8::new(12, 5, 8 ),
|
||||||
Color8::new(39, 47, 58 ),
|
Color8::new(39, 47, 58 ),
|
||||||
Color8::new(1, 9, 22 ),
|
Color8::new(1, 9, 22 ),
|
||||||
Color8::new(7, 6, 10 ),
|
Color8::new(7, 6, 10 ),
|
||||||
Color8::new(0, 0, 0 )
|
Color8::new(0, 0, 0 )
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
const RANDOM: [&[u8]; 7] = [
|
const RANDOM: [&[u8]; 7] = [
|
||||||
include_bytes!("rand/random1.in"),
|
include_bytes!("rand/random1.in"),
|
||||||
include_bytes!("rand/random2.in"),
|
include_bytes!("rand/random2.in"),
|
||||||
include_bytes!("rand/random3.in"),
|
include_bytes!("rand/random3.in"),
|
||||||
include_bytes!("rand/random4.in"),
|
include_bytes!("rand/random4.in"),
|
||||||
include_bytes!("rand/random5.in"),
|
include_bytes!("rand/random5.in"),
|
||||||
include_bytes!("rand/random6.in"),
|
include_bytes!("rand/random6.in"),
|
||||||
include_bytes!("rand/random7.in")
|
include_bytes!("rand/random7.in")
|
||||||
];
|
];
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -4,74 +4,74 @@ include!("data/rand.rs");
|
||||||
|
|
||||||
fn defl_gzip(inp: &[u8], out: &[u8])
|
fn defl_gzip(inp: &[u8], out: &[u8])
|
||||||
{
|
{
|
||||||
let b = &inp[defl::load_gzip_header(inp).unwrap()..];
|
let b = &inp[defl::load_gzip_header(inp).unwrap()..];
|
||||||
assert_eq!(defl::load_deflate(b).unwrap().1, out.to_vec());
|
assert_eq!(defl::load_deflate(b).unwrap().1, out.to_vec());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn defl_alice(inp: &[u8])
|
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]
|
#[test]
|
||||||
fn defl_alice_1()
|
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]
|
#[test]
|
||||||
fn defl_alice_2()
|
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]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn defl_shapes()
|
fn defl_shapes()
|
||||||
{
|
{
|
||||||
const INPUT: &[u8] = include_bytes!("data/defl/Shapes.in");
|
const INPUT: &[u8] = include_bytes!("data/defl/Shapes.in");
|
||||||
const OUTPUT: &[u8] = include_bytes!("data/m2/Shapes");
|
const OUTPUT: &[u8] = include_bytes!("data/m2/Shapes");
|
||||||
|
|
||||||
defl_gzip(INPUT, OUTPUT);
|
defl_gzip(INPUT, OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn defl_good_gzip_headers()
|
fn defl_good_gzip_headers()
|
||||||
{
|
{
|
||||||
defl::load_gzip_header(include_bytes!("data/gz/ok1.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/ok2.in")).unwrap();
|
||||||
defl::load_gzip_header(include_bytes!("data/gz/ok3.in")).unwrap();
|
defl::load_gzip_header(include_bytes!("data/gz/ok3.in")).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn defl_bad_gzip_headers()
|
fn defl_bad_gzip_headers()
|
||||||
{
|
{
|
||||||
for inp in &RANDOM {
|
for inp in &RANDOM {
|
||||||
assert!(defl::load_gzip_header(inp).is_err());
|
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/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/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/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/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/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/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/bad7.in")).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
fn defl_must_not_panic()
|
fn defl_must_not_panic()
|
||||||
{
|
{
|
||||||
for inp in &RANDOM {
|
for inp in &RANDOM {
|
||||||
defl::load_deflate(inp);
|
defl::load_deflate(inp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
146
tests/map.rs
146
tests/map.rs
|
@ -5,126 +5,126 @@ include!("data/rand.rs");
|
||||||
#[test]
|
#[test]
|
||||||
fn read_minf_must_process()
|
fn read_minf_must_process()
|
||||||
{
|
{
|
||||||
let inp = include_bytes!("data/map/minf.in");
|
let inp = include_bytes!("data/map/minf.in");
|
||||||
let out = include!("data/map/minf.out");
|
let out = include!("data/map/minf.out");
|
||||||
|
|
||||||
assert_eq!(map::minf::read(inp).unwrap(), out);
|
assert_eq!(map::minf::read(inp).unwrap(), out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_epnt_must_process()
|
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 inp = bin::rd_array(inp, map::epnt::read).unwrap();
|
||||||
let out = include!("data/map/epnt.out.2").to_vec();
|
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 inp = map::epnt::to_pnts(&inp);
|
||||||
let out = include!("data/map/epnt.out.1").to_vec();
|
let out = include!("data/map/epnt.out.1").to_vec();
|
||||||
|
|
||||||
assert_eq!(inp, out);
|
assert_eq!(inp, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_term_must_process()
|
fn read_term_must_process()
|
||||||
{
|
{
|
||||||
let inp = include_bytes!("data/map/term.in");
|
let inp = include_bytes!("data/map/term.in");
|
||||||
let out = include!("data/map/term.out");
|
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
|
// for better debug output, we iterate over each item
|
||||||
assert_eq!(inp.len(), out.len());
|
assert_eq!(inp.len(), out.len());
|
||||||
|
|
||||||
for (itrm, otrm) in inp.iter().zip(&out) {
|
for (itrm, otrm) in inp.iter().zip(&out) {
|
||||||
assert_eq!(itrm.groups.len(), otrm.groups.len());
|
assert_eq!(itrm.groups.len(), otrm.groups.len());
|
||||||
for (igrp, ogrp) in itrm.groups.iter().zip(&otrm.groups) {
|
for (igrp, ogrp) in itrm.groups.iter().zip(&otrm.groups) {
|
||||||
assert_eq!(igrp, ogrp);
|
assert_eq!(igrp, ogrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(itrm.faces.len(), otrm.faces.len());
|
assert_eq!(itrm.faces.len(), otrm.faces.len());
|
||||||
for (ifac, ofac) in itrm.faces.iter().zip(&otrm.faces) {
|
for (ifac, ofac) in itrm.faces.iter().zip(&otrm.faces) {
|
||||||
assert_eq!(ifac, ofac);
|
assert_eq!(ifac, ofac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn map_m2()
|
fn map_m2()
|
||||||
{
|
{
|
||||||
let inp = include_bytes!("data/m2/Map");
|
let inp = include_bytes!("data/m2/Map");
|
||||||
let mut rd = std::io::BufReader::new(&inp[..]);
|
let mut rd = std::io::BufReader::new(&inp[..]);
|
||||||
|
|
||||||
let mp = map::head::read(&mut rd).unwrap();
|
let mp = map::head::read(&mut rd).unwrap();
|
||||||
let en = map::entr::read_all(&mp).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]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn map_full_check()
|
fn map_full_check()
|
||||||
{
|
{
|
||||||
use maraiah::{bin::OptU16,
|
use maraiah::{bin::OptU16,
|
||||||
map::{data::*, lins::*, lite::*, ltfn::*, minf::*, objs::*,
|
map::{data::*, lins::*, lite::*, ltfn::*, minf::*, objs::*,
|
||||||
plac::*, pnts::*, poly::*},
|
plac::*, pnts::*, poly::*},
|
||||||
xfer::TransferMode};
|
xfer::TransferMode};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
let inp = include_bytes!("data/map/testmap.in");
|
let inp = include_bytes!("data/map/testmap.in");
|
||||||
let mut rd = std::io::BufReader::new(&inp[..]);
|
let mut rd = std::io::BufReader::new(&inp[..]);
|
||||||
|
|
||||||
let mp = map::head::read(&mut rd).unwrap();
|
let mp = map::head::read(&mut rd).unwrap();
|
||||||
let en = map::entr::read_all(&mp).unwrap();
|
let en = map::entr::read_all(&mp).unwrap();
|
||||||
let ed = map::data::read_all(mp.head(), &en).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]
|
#[test]
|
||||||
fn map_must_not_process()
|
fn map_must_not_process()
|
||||||
{
|
{
|
||||||
for inp in &RANDOM {
|
for inp in &RANDOM {
|
||||||
bin::rd_array(inp, map::fxpx::read).err().unwrap();
|
bin::rd_array(inp, map::fxpx::read).err().unwrap();
|
||||||
bin::rd_array(inp, map::lins::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).err().unwrap();
|
||||||
bin::rd_array(inp, map::lite::read_old).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::medi::read).err().unwrap();
|
||||||
bin::rd_array(inp, map::mnpx::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::note::read).err().unwrap();
|
||||||
bin::rd_array(inp, map::objs::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::plat::read).err().unwrap();
|
||||||
bin::rd_array(inp, map::poly::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::poly::read_old).err().unwrap();
|
||||||
bin::rd_array(inp, map::prpx::read).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).err().unwrap();
|
||||||
bin::rd_array(inp, map::sids::read_old).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::term::read).err().unwrap();
|
||||||
bin::rd_array(inp, map::trmg::read).err().unwrap();
|
bin::rd_array(inp, map::trmg::read).err().unwrap();
|
||||||
bin::rd_array(inp, map::wppx::read).err().unwrap();
|
bin::rd_array(inp, map::wppx::read).err().unwrap();
|
||||||
map::minf::read(inp).err().unwrap();
|
map::minf::read(inp).err().unwrap();
|
||||||
map::minf::read_old(inp).err().unwrap();
|
map::minf::read_old(inp).err().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn map_must_not_panic()
|
fn map_must_not_panic()
|
||||||
{
|
{
|
||||||
for inp in &RANDOM {
|
for inp in &RANDOM {
|
||||||
drop(bin::rd_array(inp, map::ambi::read));
|
drop(bin::rd_array(inp, map::ambi::read));
|
||||||
drop(bin::rd_array(inp, map::bonk::read));
|
drop(bin::rd_array(inp, map::bonk::read));
|
||||||
drop(bin::rd_array(inp, map::epnt::read));
|
drop(bin::rd_array(inp, map::epnt::read));
|
||||||
drop(bin::rd_array(inp, map::iidx::read));
|
drop(bin::rd_array(inp, map::iidx::read));
|
||||||
drop(bin::rd_array(inp, map::plac::read));
|
drop(bin::rd_array(inp, map::plac::read));
|
||||||
drop(bin::rd_array(inp, map::pxpx::read));
|
drop(bin::rd_array(inp, map::pxpx::read));
|
||||||
drop(bin::rd_array(inp, map::trmf::read));
|
drop(bin::rd_array(inp, map::trmf::read));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,25 +5,25 @@ include!("data/rand.rs");
|
||||||
#[test]
|
#[test]
|
||||||
fn machdr_must_process()
|
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_macbin(&mut inp), true);
|
||||||
assert_eq!(machdr::skip_mac_header(&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]
|
#[test]
|
||||||
fn machdr_must_not_process()
|
fn machdr_must_not_process()
|
||||||
{
|
{
|
||||||
for rinp in &RANDOM {
|
for rinp in &RANDOM {
|
||||||
let mut inp = std::io::Cursor::new(rinp);
|
let mut inp = std::io::Cursor::new(rinp);
|
||||||
assert_eq!(machdr::skip_macbin(&mut inp), false);
|
assert_eq!(machdr::skip_macbin(&mut inp), false);
|
||||||
assert_eq!(machdr::skip_apple_single(&mut inp), false);
|
assert_eq!(machdr::skip_apple_single(&mut inp), false);
|
||||||
assert_eq!(machdr::skip_mac_header(&mut inp), false);
|
assert_eq!(machdr::skip_mac_header(&mut inp), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,19 +5,19 @@ include!("data/rand.rs");
|
||||||
#[test]
|
#[test]
|
||||||
fn get_clut_must_process()
|
fn get_clut_must_process()
|
||||||
{
|
{
|
||||||
const INPUT: &[u8] = include_bytes!("data/pict/clut.in");
|
const INPUT: &[u8] = include_bytes!("data/pict/clut.in");
|
||||||
const OUTPUT: [Color8; 256] = include!("data/pict/clut.out");
|
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]
|
#[test]
|
||||||
fn pict_must_not_process()
|
fn pict_must_not_process()
|
||||||
{
|
{
|
||||||
for inp in &RANDOM {
|
for inp in &RANDOM {
|
||||||
assert!(pict::clut::read(inp).is_err());
|
assert!(pict::clut::read(inp).is_err());
|
||||||
assert!(pict::read(inp).is_err());
|
assert!(pict::read(inp).is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
16
tests/shp.rs
16
tests/shp.rs
|
@ -5,15 +5,15 @@ include!("data/rand.rs");
|
||||||
#[test]
|
#[test]
|
||||||
fn shp_must_not_process()
|
fn shp_must_not_process()
|
||||||
{
|
{
|
||||||
for inp in &RANDOM {
|
for inp in &RANDOM {
|
||||||
assert!(shp::bmap::read(inp).is_err());
|
assert!(shp::bmap::read(inp).is_err());
|
||||||
assert!(shp::coll::read(inp).is_err());
|
assert!(shp::coll::read(inp).is_err());
|
||||||
assert!(shp::fram::read(inp).is_err());
|
assert!(shp::fram::read(inp).is_err());
|
||||||
assert!(shp::sequ::read(inp).is_err());
|
assert!(shp::sequ::read(inp).is_err());
|
||||||
|
|
||||||
let mut inp = std::io::BufReader::new(&inp[..]);
|
let mut inp = std::io::BufReader::new(&inp[..]);
|
||||||
assert!(shp::read(&mut inp).is_err());
|
assert!(shp::read(&mut inp).is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
12
tests/snd.rs
12
tests/snd.rs
|
@ -5,13 +5,13 @@ include!("data/rand.rs");
|
||||||
#[test]
|
#[test]
|
||||||
fn snd_must_not_process()
|
fn snd_must_not_process()
|
||||||
{
|
{
|
||||||
for inp in &RANDOM {
|
for inp in &RANDOM {
|
||||||
assert!(snd::defs::read(inp).is_err());
|
assert!(snd::defs::read(inp).is_err());
|
||||||
assert!(snd::snds::read(inp).is_err());
|
assert!(snd::snds::read(inp).is_err());
|
||||||
|
|
||||||
let mut inp = std::io::BufReader::new(&inp[..]);
|
let mut inp = std::io::BufReader::new(&inp[..]);
|
||||||
assert!(snd::read(&mut inp).is_err());
|
assert!(snd::read(&mut inp).is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -11,72 +11,72 @@ set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(
|
find_package(
|
||||||
Qt5 5.6.0
|
Qt5 5.6.0
|
||||||
CONFIG
|
CONFIG
|
||||||
REQUIRED
|
REQUIRED
|
||||||
COMPONENTS Core Widgets
|
COMPONENTS Core Widgets
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(
|
add_library(
|
||||||
maraiah-tycho-hermes
|
maraiah-tycho-hermes
|
||||||
STATIC
|
STATIC
|
||||||
$ENV{OUT_DIR}/bindings.cc
|
$ENV{OUT_DIR}/bindings.cc
|
||||||
$ENV{OUT_DIR}/bindings.h
|
$ENV{OUT_DIR}/bindings.h
|
||||||
cc/interface.h
|
cc/interface.h
|
||||||
cc/main.cc
|
cc/main.cc
|
||||||
cc/mapmodel.cc
|
cc/mapmodel.cc
|
||||||
cc/mapprops.cc
|
cc/mapprops.cc
|
||||||
cc/mapview.cc
|
cc/mapview.cc
|
||||||
cc/menu.cc
|
cc/menu.cc
|
||||||
cc/project.cc
|
cc/project.cc
|
||||||
cc/tycho.h
|
cc/tycho.h
|
||||||
resources/resources.qrc
|
resources/resources.qrc
|
||||||
ui/about.ui
|
ui/about.ui
|
||||||
ui/license.ui
|
ui/license.ui
|
||||||
ui/mapprops.ui
|
ui/mapprops.ui
|
||||||
ui/mapview.ui
|
ui/mapview.ui
|
||||||
ui/menu.ui
|
ui/menu.ui
|
||||||
ui/points.ui
|
ui/points.ui
|
||||||
ui/project.ui
|
ui/project.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
maraiah-tycho-hermes
|
maraiah-tycho-hermes
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
CXX_STANDARD_REQUIRED ON
|
CXX_STANDARD_REQUIRED ON
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
maraiah-tycho-hermes
|
maraiah-tycho-hermes
|
||||||
PUBLIC
|
PUBLIC
|
||||||
$ENV{OUT_DIR}
|
$ENV{OUT_DIR}
|
||||||
cc
|
cc
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
maraiah-tycho-hermes
|
maraiah-tycho-hermes
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
maraiah-tycho-hermes
|
maraiah-tycho-hermes
|
||||||
PUBLIC
|
PUBLIC
|
||||||
-DQT_DEPRECATED_WARNINGS
|
-DQT_DEPRECATED_WARNINGS
|
||||||
-DQT_STRICT_ITERATORS
|
-DQT_STRICT_ITERATORS
|
||||||
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
|
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
|
||||||
)
|
)
|
||||||
|
|
||||||
file(
|
file(
|
||||||
GENERATE
|
GENERATE
|
||||||
OUTPUT link.txt
|
OUTPUT link.txt
|
||||||
CONTENT
|
CONTENT
|
||||||
"$<TARGET_PROPERTY:Qt5::Core,IMPORTED_LOCATION_RELEASE>
|
"$<TARGET_PROPERTY:Qt5::Core,IMPORTED_LOCATION_RELEASE>
|
||||||
$<TARGET_PROPERTY:Qt5::Widgets,IMPORTED_LOCATION_RELEASE>
|
$<TARGET_PROPERTY:Qt5::Widgets,IMPORTED_LOCATION_RELEASE>
|
||||||
$<TARGET_PROPERTY:Qt5::Gui,IMPORTED_LOCATION_RELEASE>"
|
$<TARGET_PROPERTY:Qt5::Gui,IMPORTED_LOCATION_RELEASE>"
|
||||||
|
|
|
@ -1,69 +1,69 @@
|
||||||
{
|
{
|
||||||
"beforeHeader": "interface.h",
|
"beforeHeader": "interface.h",
|
||||||
"cppFile": "",
|
"cppFile": "",
|
||||||
"rust": {
|
"rust": {
|
||||||
"dir": "",
|
"dir": "",
|
||||||
"interfaceModule": "ffi",
|
"interfaceModule": "ffi",
|
||||||
"implementationModule": "gui"
|
"implementationModule": "gui"
|
||||||
},
|
},
|
||||||
"objects": {
|
"objects": {
|
||||||
"IMapModel": {
|
"IMapModel": {
|
||||||
"type": "List",
|
"type": "List",
|
||||||
"baseClass": "IProjectModel",
|
"baseClass": "IProjectModel",
|
||||||
"functions": {
|
"functions": {
|
||||||
"open": {
|
"open": {
|
||||||
"return": "bool",
|
"return": "bool",
|
||||||
"mut": true,
|
"mut": true,
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{"name": "path", "type": "QString"}
|
{"name": "path", "type": "QString"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"save": {
|
"save": {
|
||||||
"return": "bool",
|
"return": "bool",
|
||||||
"mut": false
|
"mut": false
|
||||||
},
|
},
|
||||||
"saveAs": {
|
"saveAs": {
|
||||||
"return": "bool",
|
"return": "bool",
|
||||||
"mut": false,
|
"mut": false,
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{"name": "path", "type": "QString"}
|
{"name": "path", "type": "QString"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"propIcon": {
|
"propIcon": {
|
||||||
"return": "QString",
|
"return": "QString",
|
||||||
"mut": false,
|
"mut": false,
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{"name": "index", "type": "quint16"}
|
{"name": "index", "type": "quint16"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"deselect": {
|
"deselect": {
|
||||||
"return": "void",
|
"return": "void",
|
||||||
"mut": true
|
"mut": true
|
||||||
},
|
},
|
||||||
"select": {
|
"select": {
|
||||||
"return": "void",
|
"return": "void",
|
||||||
"mut": true,
|
"mut": true,
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{"name": "index", "type": "quint16"}
|
{"name": "index", "type": "quint16"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"dirty": {"type": "bool", "write": true}
|
"dirty": {"type": "bool", "write": true}
|
||||||
},
|
},
|
||||||
"itemProperties": {
|
"itemProperties": {
|
||||||
"propIndex": {"type": "quint64", "roles": [["display"]]}
|
"propIndex": {"type": "quint64", "roles": [["display"]]}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"IMapView": {
|
"IMapView": {
|
||||||
"type": "Object",
|
"type": "Object",
|
||||||
"baseClass": "IProjectView",
|
"baseClass": "IProjectView",
|
||||||
"functions": {
|
"functions": {
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
},
|
},
|
||||||
"itemProperties": {
|
"itemProperties": {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,81 +2,81 @@ use std::{io::prelude::*, path::{Path, PathBuf}};
|
||||||
|
|
||||||
fn gen_bindings(out_dir: &Path)
|
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.overwrite_implementation = true;
|
||||||
config.cpp_file = out_dir.join("bindings.cc");
|
config.cpp_file = out_dir.join("bindings.cc");
|
||||||
config.rust.dir = out_dir.to_path_buf();
|
config.rust.dir = out_dir.to_path_buf();
|
||||||
|
|
||||||
generate_bindings(&config).unwrap();
|
generate_bindings(&config).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cxx_build() -> PathBuf
|
fn cxx_build() -> PathBuf
|
||||||
{
|
{
|
||||||
let mut config = cmake::Config::new(".");
|
let mut config = cmake::Config::new(".");
|
||||||
|
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
config.cxxflag("-DTYCHO_DEBUG_ASSERTIONS");
|
config.cxxflag("-DTYCHO_DEBUG_ASSERTIONS");
|
||||||
}
|
}
|
||||||
|
|
||||||
config.build()
|
config.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_link_dirs(lnk: &Path) -> Vec<PathBuf>
|
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::fs::File::open(lnk).unwrap();
|
||||||
let lnk = std::io::BufReader::new(lnk);
|
let lnk = std::io::BufReader::new(lnk);
|
||||||
|
|
||||||
for path in lnk.lines() {
|
for path in lnk.lines() {
|
||||||
let path = PathBuf::from(path.unwrap());
|
let path = PathBuf::from(path.unwrap());
|
||||||
let path = path.parent().unwrap();
|
let path = path.parent().unwrap();
|
||||||
|
|
||||||
let path = if cfg!(target_os = "macos") {
|
let path = if cfg!(target_os = "macos") {
|
||||||
path.parent().unwrap()
|
path.parent().unwrap()
|
||||||
} else {
|
} else {
|
||||||
path
|
path
|
||||||
};
|
};
|
||||||
|
|
||||||
dirs.push(path.to_path_buf());
|
dirs.push(path.to_path_buf());
|
||||||
}
|
}
|
||||||
|
|
||||||
dirs
|
dirs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main()
|
fn main()
|
||||||
{
|
{
|
||||||
let (lty, dty, qtpre, cxx) = if cfg!(target_os = "macos") {
|
let (lty, dty, qtpre, cxx) = if cfg!(target_os = "macos") {
|
||||||
("framework", "framework", "Qt", "c++")
|
("framework", "framework", "Qt", "c++")
|
||||||
} else {
|
} else {
|
||||||
("dylib", "native", "Qt5", "stdc++")
|
("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 cxx_dir = cxx_build();
|
||||||
let lib_dir = cxx_dir.join("lib");
|
let lib_dir = cxx_dir.join("lib");
|
||||||
let etc_dir = cxx_dir.join("etc");
|
let etc_dir = cxx_dir.join("etc");
|
||||||
|
|
||||||
println!("cargo:rustc-link-search=native={}", lib_dir.display());
|
println!("cargo:rustc-link-search=native={}", lib_dir.display());
|
||||||
println!("cargo:rustc-link-lib=static=maraiah-tycho-hermes");
|
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 {
|
for path in dirs {
|
||||||
println!("cargo:rustc-link-search={}={}", dty, path.display());
|
println!("cargo:rustc-link-search={}={}", dty, path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("cargo:rustc-link-lib={}={}Core", lty, qtpre);
|
println!("cargo:rustc-link-lib={}={}Core", lty, qtpre);
|
||||||
println!("cargo:rustc-link-lib={}={}Widgets", lty, qtpre);
|
println!("cargo:rustc-link-lib={}={}Widgets", lty, qtpre);
|
||||||
println!("cargo:rustc-link-lib={}={}Gui", 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
|
// EOF
|
||||||
|
|
|
@ -7,41 +7,41 @@
|
||||||
|
|
||||||
class IProjectModel : public QAbstractItemModel
|
class IProjectModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
|
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using QAbstractItemModel::QAbstractItemModel;
|
using QAbstractItemModel::QAbstractItemModel;
|
||||||
|
|
||||||
virtual ~IProjectModel() {}
|
virtual ~IProjectModel() {}
|
||||||
|
|
||||||
virtual bool dirty() const = 0;
|
virtual bool dirty() const = 0;
|
||||||
virtual void setDirty(bool dirty) = 0;
|
virtual void setDirty(bool dirty) = 0;
|
||||||
|
|
||||||
virtual bool open(QString const &path) = 0;
|
virtual bool open(QString const &path) = 0;
|
||||||
virtual bool save() const = 0;
|
virtual bool save() const = 0;
|
||||||
virtual bool saveAs(QString const &path) const = 0;
|
virtual bool saveAs(QString const &path) const = 0;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void deselect() = 0;
|
virtual void deselect() = 0;
|
||||||
virtual void select(QModelIndex const &index) = 0;
|
virtual void select(QModelIndex const &index) = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dirtyChanged(bool dirty);
|
void dirtyChanged(bool dirty);
|
||||||
void deselected();
|
void deselected();
|
||||||
void selected(std::uint16_t index);
|
void selected(std::uint16_t index);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IProjectView : public QObject
|
class IProjectView : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using QObject::QObject;
|
using QObject::QObject;
|
||||||
|
|
||||||
virtual ~IProjectView() {}
|
virtual ~IProjectView() {}
|
||||||
|
|
||||||
virtual QWidget *widget() = 0;
|
virtual QWidget *widget() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
#include "tycho.h"
|
#include "tycho.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void critical_msg(char const *title, char const *msg)
|
void critical_msg(char const *title, char const *msg)
|
||||||
{
|
{
|
||||||
QMessageBox::critical(nullptr, QObject::tr(title), QObject::tr(msg));
|
QMessageBox::critical(nullptr, QObject::tr(title), QObject::tr(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main_cc(char *app_path)
|
int main_cc(char *app_path)
|
||||||
{
|
{
|
||||||
dbgPrint("cc entry");
|
dbgPrint("cc entry");
|
||||||
|
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
char *argv[] = {app_path, nullptr};
|
char *argv[] = {app_path, nullptr};
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
Menu w;
|
Menu w;
|
||||||
w.show();
|
w.show();
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,44 +1,44 @@
|
||||||
#include "tycho.h"
|
#include "tycho.h"
|
||||||
|
|
||||||
MapModel::MapModel(Project *parent) :
|
MapModel::MapModel(Project *parent) :
|
||||||
IMapModel(parent)
|
IMapModel(parent)
|
||||||
{
|
{
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapModel::~MapModel()
|
MapModel::~MapModel()
|
||||||
{
|
{
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapModel::deselect()
|
void MapModel::deselect()
|
||||||
{
|
{
|
||||||
IMapModel::deselect();
|
IMapModel::deselect();
|
||||||
|
|
||||||
emit deselected();
|
emit deselected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapModel::select(QModelIndex const &index)
|
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
|
QVariant MapModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
switch(role) {
|
switch(role) {
|
||||||
case Qt::DecorationRole: {
|
case Qt::DecorationRole: {
|
||||||
auto name = propIcon(index.row());
|
auto name = propIcon(index.row());
|
||||||
auto icon = name.front() == ':' ? QIcon(name)
|
auto icon = name.front() == ':' ? QIcon(name)
|
||||||
: QIcon::fromTheme(name);
|
: QIcon::fromTheme(name);
|
||||||
return QVariant::fromValue(icon);
|
return QVariant::fromValue(icon);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return IMapModel::data(index, role);
|
return IMapModel::data(index, role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
#include "tycho.h"
|
#include "tycho.h"
|
||||||
|
|
||||||
MapProps::MapProps(Project *parent) :
|
MapProps::MapProps(Project *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
m_mapModel(parent->mapModel())
|
m_mapModel(parent->mapModel())
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
setModal(true);
|
setModal(true);
|
||||||
|
|
||||||
auto bbox = new QDialogButtonBox(this);
|
auto bbox = new QDialogButtonBox(this);
|
||||||
bbox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
|
bbox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
|
||||||
verticalLayout->addWidget(bbox);
|
verticalLayout->addWidget(bbox);
|
||||||
|
|
||||||
connect(bbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
connect(bbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
connect(bbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
connect(bbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapProps::~MapProps()
|
MapProps::~MapProps()
|
||||||
{
|
{
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapProps::accept()
|
void MapProps::accept()
|
||||||
{
|
{
|
||||||
done(QDialog::Accepted);
|
done(QDialog::Accepted);
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
#include "tycho.h"
|
#include "tycho.h"
|
||||||
|
|
||||||
MapView::MapView(Project *parent) :
|
MapView::MapView(Project *parent) :
|
||||||
IMapView(parent),
|
IMapView(parent),
|
||||||
m_internal(parent),
|
m_internal(parent),
|
||||||
m_mapModel(parent->mapModel())
|
m_mapModel(parent->mapModel())
|
||||||
{
|
{
|
||||||
setupUi(&m_internal);
|
setupUi(&m_internal);
|
||||||
|
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapView::~MapView()
|
MapView::~MapView()
|
||||||
{
|
{
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *MapView::widget()
|
QWidget *MapView::widget()
|
||||||
{
|
{
|
||||||
return &m_internal;
|
return &m_internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
146
tycho/cc/menu.cc
146
tycho/cc/menu.cc
|
@ -1,148 +1,148 @@
|
||||||
#include "tycho.h"
|
#include "tycho.h"
|
||||||
|
|
||||||
Menu::Menu(QWidget *parent) :
|
Menu::Menu(QWidget *parent) :
|
||||||
QMainWindow(parent)
|
QMainWindow(parent)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
actionAbout->setShortcut(QKeySequence(QKeySequence::HelpContents));
|
actionAbout->setShortcut(QKeySequence(QKeySequence::HelpContents));
|
||||||
actionClose->setShortcut(QKeySequence(QKeySequence::Close));
|
actionClose->setShortcut(QKeySequence(QKeySequence::Close));
|
||||||
actionMapProps->setShortcut(QKeySequence(tr("Ctrl+P")));
|
actionMapProps->setShortcut(QKeySequence(tr("Ctrl+P")));
|
||||||
actionNew->setShortcut(QKeySequence(QKeySequence::New));
|
actionNew->setShortcut(QKeySequence(QKeySequence::New));
|
||||||
actionOpen->setShortcut(QKeySequence(QKeySequence::Open));
|
actionOpen->setShortcut(QKeySequence(QKeySequence::Open));
|
||||||
actionQuit->setShortcut(QKeySequence(QKeySequence::Quit));
|
actionQuit->setShortcut(QKeySequence(QKeySequence::Quit));
|
||||||
|
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu::~Menu()
|
Menu::~Menu()
|
||||||
{
|
{
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::mapNew()
|
void Menu::mapNew()
|
||||||
{
|
{
|
||||||
QScopedPointer proj{new Project(Project::Map)};
|
QScopedPointer proj{new Project(Project::Map)};
|
||||||
|
|
||||||
addProject(proj.take());
|
addProject(proj.take());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::mapOpen()
|
void Menu::mapOpen()
|
||||||
{
|
{
|
||||||
auto fname =
|
auto fname =
|
||||||
QFileDialog::getOpenFileName(
|
QFileDialog::getOpenFileName(
|
||||||
this,
|
this,
|
||||||
tr("Open Map File"),
|
tr("Open Map File"),
|
||||||
QString(),
|
QString(),
|
||||||
tr("Marathon Map files (*.scen *.sceA Map);;"
|
tr("Marathon Map files (*.scen *.sceA Map);;"
|
||||||
"Marathon Physics files (*.phys *.phyA Physics);;"
|
"Marathon Physics files (*.phys *.phyA Physics);;"
|
||||||
"Aleph One Image files (*.imgA);;"
|
"Aleph One Image files (*.imgA);;"
|
||||||
"All files (*)"));
|
"All files (*)"));
|
||||||
|
|
||||||
if(!fname.isEmpty()) {
|
if(!fname.isEmpty()) {
|
||||||
QScopedPointer proj{new Project(Project::Map)};
|
QScopedPointer proj{new Project(Project::Map)};
|
||||||
|
|
||||||
if(proj->model()->open(fname)) {
|
if(proj->model()->open(fname)) {
|
||||||
addProject(proj.take());
|
addProject(proj.take());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::openAbout()
|
void Menu::openAbout()
|
||||||
{
|
{
|
||||||
QDialog dlg{this};
|
QDialog dlg{this};
|
||||||
Ui::About ui{};
|
Ui::About ui{};
|
||||||
|
|
||||||
ui.setupUi(&dlg);
|
ui.setupUi(&dlg);
|
||||||
|
|
||||||
auto text = ui.labelText->text();
|
auto text = ui.labelText->text();
|
||||||
|
|
||||||
text.replace("AUTHORS",
|
text.replace("AUTHORS",
|
||||||
tr(tychoAuthors()).replace(':', ", ").toHtmlEscaped());
|
tr(tychoAuthors()).replace(':', ", ").toHtmlEscaped());
|
||||||
text.replace("HOMEPAGE", tr(tychoHomepage()));
|
text.replace("HOMEPAGE", tr(tychoHomepage()));
|
||||||
text.replace("REPOSITORY", tr(tychoRepository()));
|
text.replace("REPOSITORY", tr(tychoRepository()));
|
||||||
text.replace("VERSION", tr(tychoVersion()));
|
text.replace("VERSION", tr(tychoVersion()));
|
||||||
|
|
||||||
ui.labelText->setText(text);
|
ui.labelText->setText(text);
|
||||||
|
|
||||||
connect(ui.btnLicense, &QPushButton::clicked, this, [&](){
|
connect(ui.btnLicense, &QPushButton::clicked, this, [&](){
|
||||||
openLicense(&dlg);
|
openLicense(&dlg);
|
||||||
});
|
});
|
||||||
|
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::openAboutQt()
|
void Menu::openAboutQt()
|
||||||
{
|
{
|
||||||
QMessageBox::aboutQt(this);
|
QMessageBox::aboutQt(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::openLicense(QWidget *parent)
|
void Menu::openLicense(QWidget *parent)
|
||||||
{
|
{
|
||||||
QDialog dlg{parent};
|
QDialog dlg{parent};
|
||||||
Ui::License ui{};
|
Ui::License ui{};
|
||||||
|
|
||||||
ui.setupUi(&dlg);
|
ui.setupUi(&dlg);
|
||||||
|
|
||||||
ui.text->setPlainText(tychoLicenseText());
|
ui.text->setPlainText(tychoLicenseText());
|
||||||
|
|
||||||
connect(ui.btnCopy, &QPushButton::clicked, this, [&]() {
|
connect(ui.btnCopy, &QPushButton::clicked, this, [&]() {
|
||||||
ui.text->selectAll();
|
ui.text->selectAll();
|
||||||
ui.text->copy();
|
ui.text->copy();
|
||||||
});
|
});
|
||||||
|
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::openMapProperties()
|
void Menu::openMapProperties()
|
||||||
{
|
{
|
||||||
auto proj = activeProject();
|
auto proj = activeProject();
|
||||||
|
|
||||||
if(proj && proj->type() == Project::Map) {
|
if(proj && proj->type() == Project::Map) {
|
||||||
MapProps props{proj};
|
MapProps props{proj};
|
||||||
props.exec();
|
props.exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::updateActions()
|
void Menu::updateActions()
|
||||||
{
|
{
|
||||||
std::optional<Project::Type> active;
|
std::optional<Project::Type> active;
|
||||||
|
|
||||||
if(auto proj = activeProject()) {
|
if(auto proj = activeProject()) {
|
||||||
active = proj->type();
|
active = proj->type();
|
||||||
}
|
}
|
||||||
|
|
||||||
actionClose->setEnabled(!!active);
|
actionClose->setEnabled(!!active);
|
||||||
actionMapProps->setEnabled(active == Project::Map);
|
actionMapProps->setEnabled(active == Project::Map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::closeEvent(QCloseEvent *event)
|
void Menu::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
for(auto *win : mdiArea->subWindowList()) {
|
for(auto *win : mdiArea->subWindowList()) {
|
||||||
if(!win->close()) {
|
if(!win->close()) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
Project *Menu::activeProject() const
|
Project *Menu::activeProject() const
|
||||||
{
|
{
|
||||||
return qobject_cast<Project *>(activeSubWindow());
|
return qobject_cast<Project *>(activeSubWindow());
|
||||||
}
|
}
|
||||||
|
|
||||||
QMdiSubWindow *Menu::activeSubWindow() const
|
QMdiSubWindow *Menu::activeSubWindow() const
|
||||||
{
|
{
|
||||||
return mdiArea->activeSubWindow();
|
return mdiArea->activeSubWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::addProject(Project *proj)
|
void Menu::addProject(Project *proj)
|
||||||
{
|
{
|
||||||
auto win = mdiArea->addSubWindow(proj);
|
auto win = mdiArea->addSubWindow(proj);
|
||||||
|
|
||||||
win->showMaximized();
|
win->showMaximized();
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -3,89 +3,89 @@
|
||||||
static
|
static
|
||||||
IProjectModel *makeModel(Project *proj)
|
IProjectModel *makeModel(Project *proj)
|
||||||
{
|
{
|
||||||
switch(proj->type()) {
|
switch(proj->type()) {
|
||||||
case Project::Map: return new MapModel(proj);
|
case Project::Map: return new MapModel(proj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
IProjectView *makeView(Project *proj)
|
IProjectView *makeView(Project *proj)
|
||||||
{
|
{
|
||||||
switch(proj->type()) {
|
switch(proj->type()) {
|
||||||
case Project::Map: return new MapView(proj);
|
case Project::Map: return new MapView(proj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::Project(Type type) :
|
Project::Project(Type type) :
|
||||||
QMdiSubWindow(),
|
QMdiSubWindow(),
|
||||||
m_type(type),
|
m_type(type),
|
||||||
m_model(makeModel(this)),
|
m_model(makeModel(this)),
|
||||||
m_view(makeView(this))
|
m_view(makeView(this))
|
||||||
{
|
{
|
||||||
auto widget = new QWidget(this);
|
auto widget = new QWidget(this);
|
||||||
|
|
||||||
setupUi(widget);
|
setupUi(widget);
|
||||||
|
|
||||||
setWidget(widget);
|
setWidget(widget);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
listView->setModel(m_model);
|
listView->setModel(m_model);
|
||||||
verticalLayout->insertWidget(0, m_view->widget());
|
verticalLayout->insertWidget(0, m_view->widget());
|
||||||
|
|
||||||
connect(listView,
|
connect(listView,
|
||||||
SIGNAL(doubleClicked(QModelIndex const &)),
|
SIGNAL(doubleClicked(QModelIndex const &)),
|
||||||
m_model,
|
m_model,
|
||||||
SLOT(select(QModelIndex const &)));
|
SLOT(select(QModelIndex const &)));
|
||||||
|
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::~Project()
|
Project::~Project()
|
||||||
{
|
{
|
||||||
dbgPrintFunc();
|
dbgPrintFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::Type Project::type() const
|
Project::Type Project::type() const
|
||||||
{
|
{
|
||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
IProjectModel *Project::model() const
|
IProjectModel *Project::model() const
|
||||||
{
|
{
|
||||||
return m_model;
|
return m_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapModel *Project::mapModel() const
|
MapModel *Project::mapModel() const
|
||||||
{
|
{
|
||||||
return qobject_cast<MapModel *>(m_model);
|
return qobject_cast<MapModel *>(m_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::closeEvent(QCloseEvent *event)
|
void Project::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
if(m_model->dirty()) {
|
if(m_model->dirty()) {
|
||||||
QMessageBox msg;
|
QMessageBox msg;
|
||||||
msg.setText(tr("Do you want to save your changes to this project before closing it?"));
|
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.setInformativeText(tr("Unsaved changes will be lost unless you save."));
|
||||||
msg.setStandardButtons(QMessageBox::Save |
|
msg.setStandardButtons(QMessageBox::Save |
|
||||||
QMessageBox::Discard |
|
QMessageBox::Discard |
|
||||||
QMessageBox::Cancel);
|
QMessageBox::Cancel);
|
||||||
msg.setDefaultButton(QMessageBox::Save);
|
msg.setDefaultButton(QMessageBox::Save);
|
||||||
|
|
||||||
switch(msg.exec()) {
|
switch(msg.exec()) {
|
||||||
case QMessageBox::Save:
|
case QMessageBox::Save:
|
||||||
m_model->save();
|
m_model->save();
|
||||||
break;
|
break;
|
||||||
case QMessageBox::Discard:
|
case QMessageBox::Discard:
|
||||||
break;
|
break;
|
||||||
case QMessageBox::Cancel:
|
case QMessageBox::Cancel:
|
||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// 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
|
class MapModel final : public IMapModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MapModel(Project *parent);
|
explicit MapModel(Project *parent);
|
||||||
~MapModel() override;
|
~MapModel() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void deselect() override;
|
void deselect() override;
|
||||||
void select(QModelIndex const &index) override;
|
void select(QModelIndex const &index) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MapView final : public IMapView,
|
class MapView final : public IMapView,
|
||||||
private Ui::MapView
|
private Ui::MapView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MapView(Project *parent);
|
explicit MapView(Project *parent);
|
||||||
~MapView();
|
~MapView();
|
||||||
|
|
||||||
QWidget *widget();
|
QWidget *widget();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget m_internal;
|
QWidget m_internal;
|
||||||
MapModel *const m_mapModel;
|
MapModel *const m_mapModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MapProps final : public QDialog,
|
class MapProps final : public QDialog,
|
||||||
private Ui::MapProps
|
private Ui::MapProps
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MapProps(Project *parent);
|
explicit MapProps(Project *parent);
|
||||||
~MapProps();
|
~MapProps();
|
||||||
|
|
||||||
void accept() override;
|
void accept() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MapModel *const m_mapModel;
|
MapModel *const m_mapModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Menu final : public QMainWindow,
|
class Menu final : public QMainWindow,
|
||||||
private Ui::Menu
|
private Ui::Menu
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Menu(QWidget *parent = nullptr);
|
explicit Menu(QWidget *parent = nullptr);
|
||||||
~Menu();
|
~Menu();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void mapNew();
|
void mapNew();
|
||||||
void mapOpen();
|
void mapOpen();
|
||||||
void openAbout();
|
void openAbout();
|
||||||
void openAboutQt();
|
void openAboutQt();
|
||||||
void openMapProperties();
|
void openMapProperties();
|
||||||
void updateActions();
|
void updateActions();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
void openLicense(QWidget *parent);
|
void openLicense(QWidget *parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Project *activeProject() const;
|
Project *activeProject() const;
|
||||||
QMdiSubWindow *activeSubWindow() const;
|
QMdiSubWindow *activeSubWindow() const;
|
||||||
|
|
||||||
void addProject(Project *proj);
|
void addProject(Project *proj);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Project final : public QMdiSubWindow,
|
class Project final : public QMdiSubWindow,
|
||||||
private Ui::Project
|
private Ui::Project
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(Type type READ type CONSTANT)
|
Q_PROPERTY(Type type READ type CONSTANT)
|
||||||
Q_PROPERTY(IProjectModel *model READ model CONSTANT)
|
Q_PROPERTY(IProjectModel *model READ model CONSTANT)
|
||||||
Q_PROPERTY(MapModel *mapModel READ mapModel CONSTANT)
|
Q_PROPERTY(MapModel *mapModel READ mapModel CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Type {Map};
|
enum Type {Map};
|
||||||
Q_ENUM(Type)
|
Q_ENUM(Type)
|
||||||
|
|
||||||
explicit Project(Type type);
|
explicit Project(Type type);
|
||||||
~Project();
|
~Project();
|
||||||
|
|
||||||
Type type() const;
|
Type type() const;
|
||||||
IProjectModel *model() const;
|
IProjectModel *model() const;
|
||||||
MapModel *mapModel() const;
|
MapModel *mapModel() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type const m_type;
|
Type const m_type;
|
||||||
IProjectModel *const m_model;
|
IProjectModel *const m_model;
|
||||||
IProjectView *const m_view;
|
IProjectView *const m_view;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
|
@ -141,9 +141,9 @@ template<typename... VA>
|
||||||
static inline
|
static inline
|
||||||
void dbgPrint([[maybe_unused]] char const *fmt, [[maybe_unused]] VA &&...va)
|
void dbgPrint([[maybe_unused]] char const *fmt, [[maybe_unused]] VA &&...va)
|
||||||
{
|
{
|
||||||
#ifdef TYCHO_DEBUG_ASSERTIONS
|
#ifdef TYCHO_DEBUG_ASSERTIONS
|
||||||
qDebug(fmt, std::forward<VA>(va)...);
|
qDebug(fmt, std::forward<VA>(va)...);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
@ -153,18 +153,18 @@ void dbgPrint([[maybe_unused]] char const *fmt, [[maybe_unused]] VA &&...va)
|
||||||
constexpr
|
constexpr
|
||||||
std::uint32_t fourCC(byte a, byte b, byte c, byte d)
|
std::uint32_t fourCC(byte a, byte b, byte c, byte d)
|
||||||
{
|
{
|
||||||
return (static_cast<std::uint32_t>(a) << 24) |
|
return (static_cast<std::uint32_t>(a) << 24) |
|
||||||
(static_cast<std::uint32_t>(b) << 16) |
|
(static_cast<std::uint32_t>(b) << 16) |
|
||||||
(static_cast<std::uint32_t>(c) << 8) |
|
(static_cast<std::uint32_t>(c) << 8) |
|
||||||
static_cast<std::uint32_t>(d);
|
static_cast<std::uint32_t>(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
char const *tychoAuthors();
|
char const *tychoAuthors();
|
||||||
char const *tychoHomepage();
|
char const *tychoHomepage();
|
||||||
char const *tychoLicenseText();
|
char const *tychoLicenseText();
|
||||||
char const *tychoRepository();
|
char const *tychoRepository();
|
||||||
char const *tychoVersion();
|
char const *tychoVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
//! C++ functions.
|
//! C++ functions.
|
||||||
|
|
||||||
mod ffi {
|
mod ffi {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn critical_msg(title: maraiah::ffi::NT, msg: maraiah::ffi::NT);
|
pub fn critical_msg(title: maraiah::ffi::NT, msg: maraiah::ffi::NT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn critical_msg<T, U>(title: T, msg: U)
|
pub fn critical_msg<T, U>(title: T, msg: U)
|
||||||
where T: ToString,
|
where T: ToString,
|
||||||
U: ToString
|
U: ToString
|
||||||
{
|
{
|
||||||
let title = std::ffi::CString::new(title.to_string()).unwrap();
|
let title = std::ffi::CString::new(title.to_string()).unwrap();
|
||||||
let msg = std::ffi::CString::new(msg.to_string()).unwrap();
|
let msg = std::ffi::CString::new(msg.to_string()).unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::critical_msg(title.as_ptr(), msg.as_ptr());
|
ffi::critical_msg(title.as_ptr(), msg.as_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -6,130 +6,130 @@ use crate::cc;
|
||||||
|
|
||||||
impl IMapModel
|
impl IMapModel
|
||||||
{
|
{
|
||||||
pub fn open_map(path: String) -> ResultS<EntryDataMap>
|
pub fn open_map(path: String) -> ResultS<EntryDataMap>
|
||||||
{
|
{
|
||||||
let mut fp = maraiah::file::open_mac(path)?;
|
let mut fp = maraiah::file::open_mac(path)?;
|
||||||
|
|
||||||
let map = map::head::read(&mut fp)?;
|
let map = map::head::read(&mut fp)?;
|
||||||
let ent = map::entr::read_all(&map)?;
|
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)
|
pub fn get(&self, index: usize) -> (&u16, &EntryData)
|
||||||
{
|
{
|
||||||
self.map.iter().nth(index).unwrap()
|
self.map.iter().nth(index).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn get_mut(&mut self, index: usize) -> (&u16, &mut EntryData)
|
pub fn get_mut(&mut self, index: usize) -> (&u16, &mut EntryData)
|
||||||
{
|
{
|
||||||
self.map.iter_mut().nth(index).unwrap()
|
self.map.iter_mut().nth(index).unwrap()
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IMapModelTrait for IMapModel
|
impl IMapModelTrait for IMapModel
|
||||||
{
|
{
|
||||||
/// Returns a new `IMapModel` instance.
|
/// Returns a new `IMapModel` instance.
|
||||||
fn new(emit: IMapModelEmitter, _: IMapModelList) -> Self
|
fn new(emit: IMapModelEmitter, _: IMapModelList) -> Self
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("new IMapModel");
|
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`.
|
/// Returns the emitter of `self`.
|
||||||
fn emit(&mut self) -> &mut IMapModelEmitter {&mut self.emit}
|
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
|
fn prop_icon(&self, index: u16) -> String
|
||||||
{
|
{
|
||||||
match self.get(index.into()).1.get_type() {
|
match self.get(index.into()).1.get_type() {
|
||||||
EntryType::Image => "image-x-generic".to_string(),
|
EntryType::Image => "image-x-generic".to_string(),
|
||||||
EntryType::Map => ":/tycho/color/map.png".to_string(),
|
EntryType::Map => ":/tycho/color/map.png".to_string(),
|
||||||
EntryType::Other => "image-missing".to_string(),
|
EntryType::Other => "image-missing".to_string(),
|
||||||
EntryType::Physics => "applications-system".to_string(),
|
EntryType::Physics => "applications-system".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens the map file at `path`.
|
/// Opens the map file at `path`.
|
||||||
fn open(&mut self, path: String) -> bool
|
fn open(&mut self, path: String) -> bool
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("opening project: {}", &path);
|
eprintln!("opening project: {}", &path);
|
||||||
}
|
}
|
||||||
|
|
||||||
match Self::open_map(path) {
|
match Self::open_map(path) {
|
||||||
Ok(map) => {
|
Ok(map) => {
|
||||||
self.map = map;
|
self.map = map;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
backtrace!(e);
|
backtrace!(e);
|
||||||
cc::critical_msg("Error opening map", e);
|
cc::critical_msg("Error opening map", e);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saves the project into the original file.
|
/// Saves the project into the original file.
|
||||||
fn save(&self) -> bool
|
fn save(&self) -> bool
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("saving project");
|
eprintln!("saving project");
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saves the project into `path`.
|
/// Saves the project into `path`.
|
||||||
fn save_as(&self, path: String) -> bool
|
fn save_as(&self, path: String) -> bool
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("saving project as {}", path);
|
eprintln!("saving project as {}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the file has been modified from its original state.
|
/// Returns `true` if the file has been modified from its original state.
|
||||||
fn dirty(&self) -> bool {self.dirty}
|
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)
|
fn select(&mut self, index: u16)
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("selecting map {}", index);
|
eprintln!("selecting map {}", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.selected = Some(index);
|
self.selected = Some(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for IMapModel
|
impl Drop for IMapModel
|
||||||
{
|
{
|
||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("drop IMapModel");
|
eprintln!("drop IMapModel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IMapModel {
|
pub struct IMapModel {
|
||||||
emit: IMapModelEmitter,
|
emit: IMapModelEmitter,
|
||||||
map: EntryDataMap,
|
map: EntryDataMap,
|
||||||
selected: Option<u16>,
|
selected: Option<u16>,
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -4,32 +4,32 @@ use super::qobj::*;
|
||||||
|
|
||||||
impl IMapViewTrait for IMapView
|
impl IMapViewTrait for IMapView
|
||||||
{
|
{
|
||||||
/// Returns a new `IMapView` instance.
|
/// Returns a new `IMapView` instance.
|
||||||
fn new(emit: IMapViewEmitter) -> Self
|
fn new(emit: IMapViewEmitter) -> Self
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("new IMapView");
|
eprintln!("new IMapView");
|
||||||
}
|
}
|
||||||
|
|
||||||
Self{emit}
|
Self{emit}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the emitter of `self`.
|
/// Returns the emitter of `self`.
|
||||||
fn emit(&mut self) -> &mut IMapViewEmitter {&mut self.emit}
|
fn emit(&mut self) -> &mut IMapViewEmitter {&mut self.emit}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for IMapView
|
impl Drop for IMapView
|
||||||
{
|
{
|
||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("drop IMapView");
|
eprintln!("drop IMapView");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IMapView {
|
pub struct IMapView {
|
||||||
emit: IMapViewEmitter,
|
emit: IMapViewEmitter,
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -5,24 +5,24 @@ mod gui;
|
||||||
mod meta;
|
mod meta;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn main_cc(app_name: *mut ffi::c_char);
|
fn main_cc(app_name: *mut ffi::c_char);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> ResultS<()>
|
fn main() -> ResultS<()>
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
eprintln!("rust entry");
|
eprintln!("rust entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut args = std::env::args();
|
let mut args = std::env::args();
|
||||||
let app_name = args.next().ok_or(err_msg("bad launch name"))?;
|
let app_name = args.next().ok_or(err_msg("bad launch name"))?;
|
||||||
let app_name = ffi::CString::new(app_name)?;
|
let app_name = ffi::CString::new(app_name)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
main_cc(app_name.into_raw());
|
main_cc(app_name.into_raw());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -3,23 +3,23 @@
|
||||||
use maraiah::{ffi, meta};
|
use maraiah::{ffi, meta};
|
||||||
|
|
||||||
macro_rules! meta_str {
|
macro_rules! meta_str {
|
||||||
($($name:ident = $e:expr;)*) => {
|
($($name:ident = $e:expr;)*) => {
|
||||||
$(
|
$(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn $name() -> ffi::NT
|
pub extern "C" fn $name() -> ffi::NT
|
||||||
{
|
{
|
||||||
$e
|
$e
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_str! {
|
meta_str! {
|
||||||
tychoAuthors = meta::ffi::authors();
|
tychoAuthors = meta::ffi::authors();
|
||||||
tychoHomepage = meta::ffi::homepage();
|
tychoHomepage = meta::ffi::homepage();
|
||||||
tychoLicenseText = meta::ffi::license_text();
|
tychoLicenseText = meta::ffi::license_text();
|
||||||
tychoRepository = meta::ffi::repository();
|
tychoRepository = meta::ffi::repository();
|
||||||
tychoVersion = meta::ffi::version();
|
tychoVersion = meta::ffi::version();
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
Loading…
Reference in New Issue