Maraiah/src/main.rs

176 lines
4.3 KiB
Rust

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