Maraiah/source/leela/main.rs

255 lines
5.9 KiB
Rust
Raw Normal View History

2019-03-01 03:22:27 -08:00
use maraiah::{durandal::{err::*, file::*, image::*, sound::*},
2019-04-11 21:04:39 -07:00
marathon::{machdr, map, ppm, shp, snd, tga, wav}};
2019-03-29 11:32:17 -07:00
use std::{fs, io, slice::from_ref};
2019-03-01 01:27:28 -08:00
fn make_tga(_opt: &Options, fname: &str, im: &impl Image) -> ResultS<()>
2019-02-10 02:31:57 -08:00
{
2019-02-12 15:03:18 -08:00
let mut out = io::BufWriter::new(fs::File::create(fname)?);
2019-03-04 02:18:57 -08:00
2019-03-13 08:32:46 -07:00
tga::write_tga(&mut out, im)
}
2019-03-13 09:56:39 -07:00
fn make_ppm(_opt: &Options, fname: &str, im: &impl Image) -> ResultS<()>
{
let mut out = io::BufWriter::new(fs::File::create(fname)?);
ppm::write_ppm(&mut out, im)
}
fn make_yaml<T>(opt: &Options, data: &T) -> ResultS<()>
where T: serde::Serialize + std::fmt::Debug
{
if opt.out_debug {
println!("{:#?}", data);
} else {
serde_yaml::to_writer(io::stdout(), &data)?;
println!();
}
2019-03-04 02:18:57 -08:00
Ok(())
}
2019-02-17 18:17:35 -08:00
fn make_wav(fname: &str, snd: &impl Sound) -> ResultS<()>
{
let mut out = io::BufWriter::new(fs::File::create(fname)?);
2019-03-13 08:32:46 -07:00
wav::write_wav(&mut out, snd)
2019-02-17 18:17:35 -08:00
}
fn process_wad(opt: &Options, b: &[u8]) -> ResultS<()>
2019-02-08 20:21:22 -08:00
{
2019-04-11 21:04:39 -07:00
let wad = map::read(b)?;
2018-09-09 15:21:31 -07:00
2019-03-01 03:22:27 -08:00
if opt.wad_wrt_all {
2019-03-09 14:03:20 -08:00
make_yaml(opt, &wad)?;
2019-02-08 20:21:22 -08:00
}
2019-02-08 20:21:22 -08:00
Ok(())
}
2019-04-11 21:04:39 -07:00
fn dump_bitmaps(opt: &Options, c: &shp::coll::Collection, i: usize)
-> ResultS<()>
2019-02-12 06:41:28 -08:00
{
if !opt.shp_bmp {
return Ok(());
}
2019-02-12 06:41:28 -08:00
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);
2019-04-11 21:04:39 -07:00
make_tga(opt, &fname, &shp::bmap::ImageShp::new(bmp, &tab))?;
}
} else {
let fname = format!("{}/shape{}_{}.tga", opt.out_dir, i, j);
2019-04-11 21:04:39 -07:00
make_tga(opt, &fname, &shp::bmap::ImageShp::new(bmp, &c.tabs[0]))?;
2019-02-12 06:41:28 -08:00
}
}
Ok(())
}
2019-04-11 21:04:39 -07:00
fn write_shp_objs(opt: &Options, cl: &shp::coll::Collection) -> ResultS<()>
{
2019-03-04 02:18:57 -08:00
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(())
}
fn process_shp(opt: &Options, b: &[u8]) -> ResultS<()>
2019-02-08 20:21:22 -08:00
{
2019-04-11 21:04:39 -07:00
for (i, cl) in shp::read(b)?.iter().enumerate() {
2019-02-12 02:31:20 -08:00
if let Some(cl) = &cl.0 {
dump_bitmaps(opt, cl, i)?;
write_shp_objs(opt, cl)?;
2019-02-12 02:31:20 -08:00
}
2019-03-04 02:18:57 -08:00
2019-02-12 02:31:20 -08:00
if let Some(cl) = &cl.1 {
dump_bitmaps(opt, cl, i + 100)?;
write_shp_objs(opt, cl)?;
2019-02-12 02:31:20 -08:00
}
}
Ok(())
2018-09-06 09:01:52 -07:00
}
2019-02-17 20:04:04 -08:00
fn dump_sounds(opt: &Options, st: &snd::SoundTable, c: usize) -> ResultS<()>
2019-02-17 18:17:35 -08:00
{
2019-02-17 20:04:04 -08:00
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)?;
2019-02-17 18:17:35 -08:00
}
}
Ok(())
}
2019-02-17 20:04:04 -08:00
fn process_snd(opt: &Options, b: &[u8]) -> ResultS<()>
{
2019-04-11 21:04:39 -07:00
for (c, st) in snd::read(b)?.iter().enumerate() {
2019-02-17 20:04:04 -08:00
dump_sounds(opt, st, c)?;
}
Ok(())
}
2019-03-13 09:56:39 -07:00
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)
}
2019-02-08 20:21:22 -08:00
fn main() -> ResultS<()>
{
2019-02-12 09:53:25 -08:00
use argparse::*;
2019-02-08 20:21:22 -08:00
2019-03-27 02:32:25 -07:00
let mut opt = Options::default();
2019-02-12 09:53:25 -08:00
{
2019-02-18 20:18:08 -08:00
let mut ap = ArgumentParser::new();
2019-02-17 20:04:04 -08:00
macro_rules! arg {
2019-02-18 20:18:08 -08:00
($name:expr, $ref:expr, $type:expr, $desc:expr) => {
2019-03-29 11:32:17 -07:00
ap.refer(&mut $ref).add_option(from_ref(&$name), $type, $desc);
2019-02-18 20:06:34 -08:00
};
2019-02-17 20:04:04 -08:00
}
2019-02-12 09:53:25 -08:00
ap.set_description(env!("CARGO_PKG_DESCRIPTION"));
2019-02-17 20:04:04 -08:00
2019-02-12 09:53:25 -08:00
ap.add_option(&["-v", "--version"],
2019-02-12 15:03:18 -08:00
Print(concat!(env!("CARGO_PKG_NAME"),
" ",
env!("CARGO_PKG_VERSION")).to_string()),
2019-02-12 09:53:25 -08:00
"Show the version");
2019-02-17 20:04:04 -08:00
ap.refer(&mut opt.inputs)
.add_argument("inputs", Collect, "Input files");
2019-02-17 20:04:04 -08:00
2019-02-20 18:33:57 -08:00
arg!("--shp-write-tab",
opt.shp_tab,
StoreTrue,
2019-02-17 20:04:04 -08:00
"shp: Dump all CLUTs as YAML to standard output");
2019-02-20 18:33:57 -08:00
arg!("--shp-dump-bitmaps",
opt.shp_bmp,
StoreTrue,
2019-02-17 20:04:04 -08:00
"shp: Dump bitmaps into a folder");
2019-02-20 18:33:57 -08:00
arg!("--shp-dump-more-bitmaps",
opt.shp_bmp_all,
StoreTrue,
2019-02-17 20:04:04 -08:00
"shp: Dump all color variations of each bitmap");
2019-02-20 18:33:57 -08:00
arg!("--shp-write-frm",
opt.shp_frm,
StoreTrue,
2019-02-17 20:04:04 -08:00
"shp: Dump all frames as YAML to standard output");
2019-02-20 18:33:57 -08:00
arg!("--shp-write-seq",
opt.shp_seq,
StoreTrue,
2019-02-17 20:04:04 -08:00
"shp: Dump all sequences as YAML to standard output");
2019-02-20 18:33:57 -08:00
arg!("--snd-dump",
opt.snd_dump,
StoreTrue,
2019-02-17 20:04:04 -08:00
"snd: Dump all sounds to WAVE files");
2019-02-22 17:35:07 -08:00
arg!("--wad-write-all",
opt.wad_wrt_all,
StoreTrue,
"wad: Dump all known chunks");
2019-02-20 18:33:57 -08:00
arg!("--out-dir",
opt.out_dir,
Store,
2019-02-17 20:04:04 -08:00
"Sets output directory for dump options");
2019-02-20 18:33:57 -08:00
arg!("--out-debug",
opt.out_debug,
StoreTrue,
2019-02-17 20:04:04 -08:00
"Writes debugging output rather than YAML");
2019-02-12 09:53:25 -08:00
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 {
2019-02-08 20:21:22 -08:00
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)?;
2019-03-31 12:04:18 -07:00
let mm = unsafe {memmap::Mmap::map(&fp)?};
2019-02-18 20:06:34 -08:00
let b = &mm[machdr::try_mac_header(&mm)..];
2019-02-08 20:21:22 -08:00
match typ {
"wad:" => process_wad(&opt, b),
"shp:" => process_shp(&opt, b),
2019-02-17 18:17:35 -08:00
"snd:" => process_snd(&opt, b),
2019-03-13 09:56:39 -07:00
"ppm:" => process_ppm(&opt, b),
2019-03-04 02:18:57 -08:00
_ => Err(err_msg("invalid file type specified on commandline")),
2019-02-08 20:21:22 -08:00
}?;
}
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,
2019-02-17 20:04:04 -08:00
snd_dump: bool,
2019-02-22 17:35:07 -08:00
wad_wrt_all: bool,
}
2018-09-06 09:01:52 -07:00
// EOF