diff --git a/.gitignore b/.gitignore index 212280d..86fe16e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target +/out **/*.rs.bk Cargo.lock perf.data* diff --git a/src/durandal/mod.rs b/src/durandal/mod.rs index ae1e662..da2ef0e 100644 --- a/src/durandal/mod.rs +++ b/src/durandal/mod.rs @@ -1,6 +1,5 @@ //! Library for various utilities. -#[allow(dead_code)] pub mod bin; #[macro_use] pub mod cenum; diff --git a/src/main.rs b/src/main.rs index 319efa4..b1c0d9a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ -use maraiah::durandal::{chunk::*, err::*, image::Image}; +use maraiah::durandal::{bin::*, chunk::*, err::*, image::Image, text::*}; use maraiah::marathon::{machdr, map, pict, term, wad}; -use memmap::Mmap; use std::{io, io::Write, fs, env}; fn write_ppm(fname: &str, im: &Image) -> io::Result<()> @@ -20,54 +19,154 @@ fn write_ppm(fname: &str, im: &Image) -> io::Result<()> Ok(()) } -fn main() -> ResultS<()> +fn read_chunk(cid: &Ident, cnk: &[u8], eid: u16) -> ResultS<()> { - let arg = env::args().nth(1).expect("need at least 1 argument"); - let fp = fs::File::open(arg)?; - let mm = unsafe{Mmap::map(&fp)?}; - let wad = wad::Wad::new(&mm[machdr::try_mac_header(&mm)..])?; + 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 (id, ent) in wad.entries { - if let Some(b) = ent.chunks.get(b"PICT") { - let im = pict::load_pict(b)?; - println!("entry {} has PICT {}x{}", id, im.w(), im.h()); - write_ppm(&format!("out_{}.ppm", id), &im)?; - } - - if let Some(b) = ent.chunks.get(b"Minf") { - let minf = map::Minf::chunk(b)?; - println!("entry {} has {:#?}", id, minf); - } - - if let Some(b) = ent.chunks.get(b"EPNT") { - let epnt = map::Endpoint::chunk(b)?; - println!("entry {} has EPNT {:#?}", id, epnt); - } - - if let Some(b) = ent.chunks.get(b"PNTS") { - let epnt = map::Point::chunk(b)?; - println!("entry {} has PNTS {:#?}", id, epnt); - } - - if let Some(b) = ent.chunks.get(b"LINS") { - let line = map::Line::chunk(b)?; - println!("entry {} has LINS {:#?}", id, line); - } - - if let Some(b) = ent.chunks.get(b"SIDS") { - let line = map::Side::chunk(b)?; - println!("entry {} has SIDS {:#?}", id, line); - } - - if let Some(b) = ent.chunks.get(b"term") { - let term = term::Terminal::chunk(b)?; - println!("entry {} has term {:#?}", id, term); + 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