Maraiah/src/marathon/wad.rs

101 lines
2.1 KiB
Rust

//! Marathon Wad format handling.
use std::collections::BTreeMap;
use std::fmt;
use durandal::bin::*;
use durandal::machead::try_mac_header;
use durandal::text::mac_roman_conv;
type Chunk <'a> = &'a[u8];
type ChunkMap<'a> = BTreeMap<Ident, Chunk<'a>>;
type EntryMap<'a> = BTreeMap<u16 , Entry<'a>>;
pub struct Entry<'a>
{
map: ChunkMap<'a>,
ext: &'a[u8],
}
#[derive(Debug)]
pub struct Wad<'a>
{
ver: u16,
dvr: u16,
ext: usize,
nam: String,
ent: EntryMap<'a>,
}
impl<'a> fmt::Debug for Entry<'a>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
write!(f, "Entry {{ ")?;
for (k, _) in &self.map {write!(f, "{} ", mac_roman_conv(&k[..]))?}
write!(f, "}}")
}
}
impl<'a> Wad<'a>
{
pub fn new(b: &[u8]) -> Wad
{
let b = &b[try_mac_header(b)..];
let ver = b_u16b(&b[ 0.. 2]);
let dvr = b_u16b(&b[ 2.. 4]);
let nam = &b[ 4..68];
let crc = b_u32b(&b[68..72]);
let dir = b_u32b(&b[72..76]) as usize;
let num = b_u16b(&b[76..78]) as usize;
let ext = b_u16b(&b[78..80]) as usize;
println!("{:x}", crc);
Wad{ver, dvr, ext,
nam: mac_roman_conv(nam),
ent: get_entries(num, ext, dir, b)}
}
}
fn get_entries(num: usize, ext: usize, dir: usize, b: &[u8]) -> EntryMap
{
let mut p = dir;
let mut map = EntryMap::new();
for _ in 0..num
{
let ofs = b_u32b(&b[p+0..p+ 4]) as usize;
let len = b_u32b(&b[p+4..p+ 8]) as usize;
let ind = b_u16b(&b[p+8..p+10]);
let ent = Entry{map: get_chunks(&b[ ofs.. ofs+len]),
ext: &b[p+10..p+10+ext]};
map.insert(ind, ent);
p += 10 + ext;
}
map
}
fn get_chunks(b: &[u8]) -> ChunkMap
{
let mut p = 0;
let mut map = ChunkMap::new();
while p < b.len()
{
let k = b_iden(&b[p+ 0..p+ 4]);
// nx = b_u32b(&b[p+ 4..p+ 8]);
let l = b_u32b(&b[p+ 8..p+12]) as usize;
// ?? = b_u32b(&b[p+12..p+16]);
map.insert(k, &b[p+16..p+ l]);
p += l + 16;
}
map
}
// EOF