leela: rewrite using clap

gui-branch-qt
an 2019-05-30 03:11:05 -04:00
parent 17856bbe7e
commit 4357a2be84
2 changed files with 60 additions and 194 deletions

View File

@ -7,7 +7,7 @@ description = "Maraiah testbed program."
edition = "2018"
[dependencies]
argparse = "0.2"
clap = "2"
maraiah = {path = "../..", features = ["serde_obj"]}
memmap = "0.7"
serde = "1.0"

View File

@ -1,244 +1,110 @@
#![allow(clippy::unit_arg)]
use maraiah::{durandal::{err::*, file::*, image::*, sound::*},
marathon::{machdr, map, ppm, shp, snd, tga, wav}};
use std::{fs, io, slice::from_ref};
fn make_tga(_opt: &Options, fname: &str, im: &impl Image) -> ResultS<()>
fn open(path: &str) -> ResultS<memmap::Mmap>
{
let mut out = io::BufWriter::new(fs::File::create(fname)?);
tga::write_tga(&mut out, im)
let fp = fs::File::open(path)?;
Ok(unsafe {memmap::Mmap::map(&fp)?})
}
fn make_ppm(_opt: &Options, fname: &str, im: &impl Image) -> ResultS<()>
fn file_read<T, F>(path: &str, f: F) -> ResultS<T>
where F: FnOnce(&[u8]) -> ResultS<T>
{
let mut out = io::BufWriter::new(fs::File::create(fname)?);
let mm = open(path)?;
let bp = &mm[machdr::try_mac_header(&mm)..];
ppm::write_ppm(&mut out, im)
f(bp)
}
fn make_yaml<T>(opt: &Options, data: &T) -> ResultS<()>
where T: serde::Serialize + std::fmt::Debug
fn exists(path: String) -> Result<(), String>
{
if opt.out_debug {
println!("{:#?}", data);
} else {
serde_yaml::to_writer(io::stdout(), &data)?;
println!();
match std::fs::metadata(path) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
Ok(())
}
fn make_wav(fname: &str, snd: &impl Sound) -> ResultS<()>
{
let mut out = io::BufWriter::new(fs::File::create(fname)?);
wav::write_wav(&mut out, snd)
}
fn process_wad(opt: &Options, b: &[u8]) -> ResultS<()>
{
let wad = map::read(b)?;
make_yaml(opt, &wad)?;
Ok(())
}
fn dump_bitmaps(opt: &Options, c: &shp::coll::Collection, i: usize)
fn each_value<'a, F>(opt: &'a clap::ArgMatches<'a>, name: &str, mut f: F)
-> ResultS<()>
where F: FnMut(&'a str) -> ResultS<()>
{
if !opt.shp_bmp {
return Ok(());
}
for (j, bmp) in c.bmps.iter().enumerate() {
if opt.shp_bmp_all {
for (k, tab) in c.tabs.iter().enumerate() {
let fname = format!("{}/shape{}_{}_{}.tga", opt.out_dir, i, j, k);
make_tga(opt, &fname, &shp::bmap::ImageShp::new(bmp, &tab))?;
}
} else {
let fname = format!("{}/shape{}_{}.tga", opt.out_dir, i, j);
make_tga(opt, &fname, &shp::bmap::ImageShp::new(bmp, &c.tabs[0]))?;
if let Some(values) = opt.values_of(name) {
for value in values {
f(value)?;
}
}
Ok(())
}
fn write_shp_objs(opt: &Options, cl: &shp::coll::Collection) -> ResultS<()>
fn dump_info(data: impl std::fmt::Debug)
{
if opt.shp_tab {make_yaml(opt, &cl.tabs)?;}
if opt.shp_frm {make_yaml(opt, &cl.frms)?;}
if opt.shp_seq {make_yaml(opt, &cl.seqs)?;}
Ok(())
println!("{:#?}", data);
}
fn process_shp(opt: &Options, b: &[u8]) -> ResultS<()>
fn sub_data_c<'a>(_opt: &clap::ArgMatches<'a>) -> ResultS<()>
{
for (i, cl) in shp::read(b)?.iter().enumerate() {
if let Some(cl) = &cl.0 {
dump_bitmaps(opt, cl, i)?;
write_shp_objs(opt, cl)?;
}
if let Some(cl) = &cl.1 {
dump_bitmaps(opt, cl, i + 100)?;
write_shp_objs(opt, cl)?;
}
}
Ok(())
unimplemented!();
}
fn dump_sounds(opt: &Options, st: &snd::SoundTable, c: usize) -> ResultS<()>
fn sub_dump_c<'a>(_opt: &clap::ArgMatches<'a>) -> ResultS<()>
{
if !opt.snd_dump {
return Ok(());
}
for (k, sd) in st {
for (i, snd) in sd.sounds.iter().enumerate() {
let fname = format!("{}/snd{}_{}_{}.wav", opt.out_dir, c, k, i);
make_wav(&fname, snd)?;
}
}
Ok(())
unimplemented!();
}
fn process_snd(opt: &Options, b: &[u8]) -> ResultS<()>
fn sub_info_c<'a>(opt: &clap::ArgMatches<'a>) -> ResultS<()>
{
for (c, st) in snd::read(b)?.iter().enumerate() {
dump_sounds(opt, st, c)?;
}
each_value(opt, "map", |f| Ok(dump_info(file_read(f, map::read)?)))?;
each_value(opt, "shp", |f| Ok(dump_info(file_read(f, shp::read)?)))?;
each_value(opt, "snd", |f| Ok(dump_info(file_read(f, snd::read)?)))?;
Ok(())
}
fn process_ppm(opt: &Options, b: &[u8]) -> ResultS<()>
{
let im = ppm::read_ppm(b)?;
let fname = format!("{}/out.tga", opt.out_dir);
make_tga(opt, &fname, &im)?;
let fname = format!("{}/out.ppm", opt.out_dir);
make_ppm(opt, &fname, &im)
}
fn main() -> ResultS<()>
{
use argparse::*;
use clap::clap_app;
let mut opt = Options::default();
{
let mut ap = ArgumentParser::new();
let sub_data =
clap_app!(@subcommand data =>
(about: "Dumps data into a discrete folder/YAML format"));
macro_rules! arg {
($name:expr, $ref:expr, $type:expr, $desc:expr) => {
ap.refer(&mut $ref).add_option(from_ref(&$name), $type, $desc);
};
}
let sub_dump =
clap_app!(@subcommand dump =>
(about: "Dumps particular parts of data"));
ap.set_description(env!("CARGO_PKG_DESCRIPTION"));
let sub_info =
clap_app!(@subcommand info =>
(about: "Outputs debug info")
(@group files =>
(@attributes +required +multiple)
(@arg map: -m --map [file]... {exists} "Loads a Map file")
(@arg shp: -s --shp [file]... {exists} "Loads a Shapes file")
(@arg snd: -n --snd [file]... {exists} "Loads a Sounds file")));
ap.add_option(&["-v", "--version"],
Print(concat!(env!("CARGO_PKG_NAME"),
" ",
env!("CARGO_PKG_VERSION")).to_string()),
"Show the version");
let opt =
clap_app!((env!("CARGO_PKG_NAME")) =>
(version: env!("CARGO_PKG_VERSION"))
(author: env!("CARGO_PKG_AUTHORS"))
(about: env!("CARGO_PKG_DESCRIPTION"))
(setting: clap::AppSettings::SubcommandRequiredElseHelp)
(subcommand: sub_data)
(subcommand: sub_dump)
(subcommand: sub_info));
ap.refer(&mut opt.inputs)
.add_argument("inputs", Collect, "Input files");
let opt = opt.get_matches();
arg!("--shp-write-tab",
opt.shp_tab,
StoreTrue,
"shp: Dump all CLUTs as YAML to standard output");
arg!("--shp-dump-bitmaps",
opt.shp_bmp,
StoreTrue,
"shp: Dump bitmaps into a folder");
arg!("--shp-dump-more-bitmaps",
opt.shp_bmp_all,
StoreTrue,
"shp: Dump all color variations of each bitmap");
arg!("--shp-write-frm",
opt.shp_frm,
StoreTrue,
"shp: Dump all frames as YAML to standard output");
arg!("--shp-write-seq",
opt.shp_seq,
StoreTrue,
"shp: Dump all sequences as YAML to standard output");
arg!("--snd-dump",
opt.snd_dump,
StoreTrue,
"snd: Dump all sounds to WAVE files");
arg!("--out-dir",
opt.out_dir,
Store,
"Sets output directory for dump options");
arg!("--out-debug",
opt.out_debug,
StoreTrue,
"Writes debugging output rather than YAML");
ap.parse_args_or_exit();
}
if opt.shp_bmp_all {
opt.shp_bmp = true;
}
if opt.out_dir.is_empty() {
opt.out_dir = ".".to_string();
}
validate_folder_path(&opt.out_dir)?;
for arg in &opt.inputs {
let (typ, fna) = if let Some(st) = arg.find(':') {
arg.split_at(st + 1)
} else {
("wad:", arg.as_str())
};
let fp = fs::File::open(fna)?;
let mm = unsafe {memmap::Mmap::map(&fp)?};
let b = &mm[machdr::try_mac_header(&mm)..];
match typ {
"wad:" => process_wad(&opt, b),
"shp:" => process_shp(&opt, b),
"snd:" => process_snd(&opt, b),
"ppm:" => process_ppm(&opt, b),
_ => Err(err_msg("invalid file type specified on commandline")),
}?;
match opt.subcommand() {
("data", Some(opt)) => sub_data_c(opt)?,
("dump", Some(opt)) => sub_dump_c(opt)?,
("info", Some(opt)) => sub_info_c(opt)?,
_ => unreachable!(),
}
Ok(())
}
#[derive(Default)]
struct Options
{
inputs: Vec<String>,
out_dir: String,
out_debug: bool,
shp_tab: bool,
shp_bmp: bool,
shp_bmp_all: bool,
shp_frm: bool,
shp_seq: bool,
snd_dump: bool,
}
// EOF