use maraiah::{durandal::{bin::*, chunk::*, err::*, image::Image, text::*}, marathon::{machdr, map, pict, term, wad}}; use std::{env, fs, io::{self, Write}}; fn write_ppm(fname: &str, im: &Image) -> io::Result<()> { let out = fs::File::create(fname)?; let mut out = io::BufWriter::new(out); write!(&mut out, "P3\n{} {}\n255\n", im.w(), im.h())?; for y in 0..im.h() { for x in 0..im.w() { let cr = &im[(x, y)]; write!(&mut out, "{} {} {} ", cr.r, cr.g, cr.b)?; } } Ok(()) } fn read_chunk(cid: &Ident, cnk: &[u8], eid: u16) -> ResultS<()> { match cid { b"PICT" => { let im = pict::load_pict(cnk)?; println!("entry {} has PICT {}x{}", eid, im.w(), im.h()); write_ppm(&format!("out/{}.ppm", eid), &im)?; } b"Minf" => { let minf = map::Minf::chunk(cnk)?; println!("entry {} has {:#?}", eid, minf); } b"EPNT" => { let epnt = map::Endpoint::chunk(cnk)?; println!("entry {} has EPNT {:#?}", eid, epnt); } b"PNTS" => { let epnt = map::Point::chunk(cnk)?; println!("entry {} has PNTS {:#?}", eid, epnt); } b"LINS" => { let line = map::Line::chunk(cnk)?; println!("entry {} has LINS {:#?}", eid, line); } b"SIDS" => { let line = map::Side::chunk(cnk)?; println!("entry {} has SIDS {:#?}", eid, line); } b"term" => { let term = term::Terminal::chunk(cnk)?; println!("entry {} has term {:#?}", eid, term); } cid => { 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 process_wad(b: &[u8]) -> ResultS<()> { let wad = wad::Wad::new(b)?; println!("{:#?}", wad); for (eid, ent) in wad.entries { for (cid, cnk) in ent.chunks { read_chunk(&cid, cnk, eid)?; } } Ok(()) } fn collection(b: &[u8]) -> ResultS<()> { let version = b.c_u16b(0)?; let dt_type = b.c_u16b(2)?; let flags = b.c_u16b(4)?; let colors = b.c_u16b(6)?; let clu_num = b.c_u16b(8)?; let clu_ofs = b.c_u32b(10)?; let seq_num = b.c_u16b(14)?; let seq_ofs = b.c_u32b(16)?; let frm_num = b.c_u16b(20)?; let frm_ofs = b.c_u32b(22)?; let bmp_num = b.c_u16b(26)?; let bmp_ofs = b.c_u32b(28)?; let scale = b.c_i16b(30)?; let size = b.c_u32b(32)?; dbg!(version); dbg!(dt_type); dbg!(flags); dbg!(colors); dbg!(clu_num); dbg!(clu_ofs); dbg!(seq_num); dbg!(seq_ofs); dbg!(frm_num); dbg!(frm_ofs); dbg!(bmp_num); dbg!(bmp_ofs); dbg!(scale); dbg!(size); eprintln!("[end of collection]"); if version != 3 { return Err(err_msg("invalid collection version number")); } Ok(()) } fn process_shp(b: &[u8]) -> ResultS<()> { for i in 0..32 { let p = 32 * i; let status = b.c_u16b(p + 0)?; let flags = b.c_u16b(p + 2)?; let offset_lo = b.c_u32b(p + 4)? as usize; let length_lo = b.c_u32b(p + 8)? as usize; let offset_hi = b.c_u32b(p + 12)? as usize; let length_hi = b.c_u32b(p + 16)? as usize; dbg!(i); dbg!(status); dbg!(flags); dbg!(offset_lo); dbg!(length_lo); dbg!(offset_hi); dbg!(length_hi); if offset_lo != u32::max_value() as usize { eprintln!("collection {} has lo-res frames", i); collection(&b[offset_lo..offset_lo + length_lo])?; } if offset_hi != u32::max_value() as usize { eprintln!("collection {} has hi-res frames", i); collection(&b[offset_hi..offset_hi + length_hi])?; } } Ok(()) } fn main() -> ResultS<()> { use memmap::Mmap; for arg in env::args().skip(1) { 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 = &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