use maraiah::{durandal::{bin::*, chunk::*, err::*, image::*, text::*}, marathon::{machdr, map, pict, shp, term, wad}}; use std::{fs, io::{self, Write}}; fn write_chunk(cid: &Ident, cnk: &[u8], eid: u16) -> ResultS<()> { let fname = format!("out/{:04}{}.bin", eid, mac_roman_conv(cid)); let out = fs::File::create(&fname)?; let mut out = io::BufWriter::new(out); out.write(cnk)?; Ok(()) } fn read_chunk(cid: &Ident, cnk: &[u8], eid: u16) -> ResultS<()> { match cid { b"PICT" => { let im = pict::load_pict(cnk)?; eprintln!("entry {} has PICT {}x{}", eid, im.w(), im.h()); let out = fs::File::create(&format!("out/{}.ppm", eid))?; let mut out = io::BufWriter::new(out); write_ppm(&mut out, &im)?; } b"Minf" => { let minf = map::Minf::chunk(cnk)?; eprintln!("entry {} has {:#?}", eid, minf); } b"EPNT" => { let epnt = map::Endpoint::chunk(cnk)?; eprintln!("entry {} has EPNT {:#?}", eid, epnt); } b"PNTS" => { let epnt = map::Point::chunk(cnk)?; eprintln!("entry {} has PNTS {:#?}", eid, epnt); } b"LINS" => { let line = map::Line::chunk(cnk)?; eprintln!("entry {} has LINS {:#?}", eid, line); } b"SIDS" => { let line = map::Side::chunk(cnk)?; eprintln!("entry {} has SIDS {:#?}", eid, line); } b"term" => { let term = term::Terminal::chunk(cnk)?; eprintln!("entry {} has term {:#?}", eid, term); } cid => { write_chunk(cid, cnk, eid)?; } } Ok(()) } fn process_wad(b: &[u8]) -> ResultS<()> { let wad = wad::Wad::new(b)?; eprintln!("{:#?}", wad); for (eid, ent) in wad.entries { for (cid, cnk) in ent.chunks { read_chunk(&cid, cnk, eid)?; } } Ok(()) } fn dump_bitmaps(c: &shp::Collection, i: usize) -> ResultS<()> { for (j, bmp) in c.bmps.iter().enumerate() { for (k, tab) in c.tabs.iter().enumerate() { let fname = format!("out/shape{}_{}_{}.tga", i, j, k); let out = fs::File::create(&fname)?; let mut out = io::BufWriter::new(out); write_tga(&mut out, &shp::ImageShp::new(bmp, &tab))?; } } Ok(()) } fn process_shp(b: &[u8]) -> ResultS<()> { for (i, cl) in shp::read_shapes(b)?.iter().enumerate() { if let Some(cl) = &cl.0 { dump_bitmaps(cl, i)?; eprintln!("<{} lo> {:#?}\n{:#?}", i, cl.frms, cl.seqs); } if let Some(cl) = &cl.1 { dump_bitmaps(cl, i + 100)?; eprintln!("<{} hi> {:#?}\n{:#?}", i, cl.frms, cl.seqs); } } Ok(()) } fn main() -> ResultS<()> { use argparse::*; use memmap::Mmap; let mut args: Vec = Vec::new(); { let mut ap = ArgumentParser::new(); ap.set_description(env!("CARGO_PKG_DESCRIPTION")); ap.add_option(&["-v", "--version"], Print(format!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"))), "Show the version"); ap.refer(&mut args) .add_argument("inputs", List, "Input files"); ap.parse_args_or_exit(); } for arg in &args { 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 {Mmap::map(&fp)?}; let b = c_data(&mm, machdr::try_mac_header(&mm)..)?; match typ { "wad:" => process_wad(b), "shp:" => process_shp(b), _ => Err(err_msg("invalid file type specified on commandline")), }?; } Ok(()) } // EOF