read_data

png-branch
an 2019-02-18 23:06:34 -05:00
parent b08c370530
commit baeea71fe4
10 changed files with 533 additions and 379 deletions

View File

@ -2,106 +2,122 @@
use crate::durandal::err::*; use crate::durandal::err::*;
use serde::Serialize; use serde::Serialize;
use std::{fmt, num::NonZeroU16, slice::SliceIndex}; use std::{fmt, num::NonZeroU16};
/// Returns a `[u8]` from `b` at `i`. #[doc(hidden)]
pub fn c_data<I>(b: &[u8], i: I) -> ResultS<&<I as SliceIndex<[u8]>>::Output> macro_rules! rd_1 {
where I: SliceIndex<[u8]> // big endian
{ (BE $b:ident $nam:ident u16 $n:expr) => {
ok!(b.get(i), "not enough data") rd_1!($b u16::from_be_bytes, $nam 2 $n);
};
(BE $b:ident $nam:ident i16 $n:expr) => {
rd_1!($b i16::from_be_bytes, $nam 2 $n);
};
(BE $b:ident $nam:ident u32 $n:expr) => {
rd_1!($b u32::from_be_bytes, $nam 4 $n);
};
(BE $b:ident $nam:ident i32 $n:expr) => {
rd_1!($b i32::from_be_bytes, $nam 4 $n);
};
(BE $b:ident $nam:ident as usize u16 $n:expr) => {
rd_1!($b u16::from_be_bytes, $nam 2 $n);
let $nam = $nam as usize;
};
(BE $b:ident $nam:ident as usize u32 $n:expr) => {
rd_1!($b u32::from_be_bytes, $nam 4 $n);
let $nam = $nam as usize;
};
// little endian
(LE $b:ident $nam:ident u16 $n:expr) => {
rd_1!($b u16::from_le_bytes $nam 2 $n);
};
(LE $b:ident $nam:ident i16 $n:expr) => {
rd_1!($b i16::from_le_bytes $nam 2 $n);
};
(LE $b:ident $nam:ident u32 $n:expr) => {
rd_1!($b u32::from_le_bytes $nam 4 $n);
};
(LE $b:ident $nam:ident i32 $n:expr) => {
rd_1!($b i32::from_le_bytes $nam 4 $n);
};
(LE $b:ident $nam:ident as usize u16 $n:expr) => {
rd_1!($b u16::from_le_bytes $nam 2 $n);
let $nam = $nam as usize;
};
(LE $b:ident $nam:ident as usize u32 $n:expr) => {
rd_1!($b u32::from_le_bytes $nam 4 $n);
let $nam = $nam as usize;
};
// generic endianness
($_:ident $b:ident $nam:ident u8 $n:expr) => {
let $nam = $b[$n];
};
($_:ident $b:ident $nam:ident array u8 $n:expr) => {
let $nam = &$b[$n];
};
($_:ident $b:ident $nam:ident i8 $n:expr) => {
let $nam = $b[$n] as i8;
};
($_:ident $b:ident $nam:ident iden $n:expr) => {
let $nam = [$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]];
};
($_:ident $b:ident $nam:ident $f:ident $n:expr) => {
let $nam = $f(&$b[$n])?;
};
($_:ident $b:ident $nam:ident nt $f:ident $n:expr) => {
let $nam = $f(&$b[$n]);
};
// worker - creates let statement
($b:ident $pth:path , $nam:ident 2 $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1]]);
};
($b:ident $pth:path , $nam:ident 4 $n:expr) => {
let $nam = $pth([$b[$n], $b[$n + 1], $b[$n + 2], $b[$n + 3]]);
};
} }
/// Returns a `u8` from `b` at `i`. macro_rules! read_data {
pub fn c_byte(b: &[u8], i: usize) -> ResultS<u8> (
{ $sz:expr , $ty:ident in $b:ident =>
match b.get(i) { $( $nam:ident = $t:ident [ $n:expr ] $( $ex:ident )* ; )*
Some(&v) => Ok(v), ) => {
None => Err(err_msg("not enough data")), if $b.len() < $sz {
bail!("not enough data");
} }
$(rd_1!($ty $b $nam $($ex)* $t $n);)*
};
} }
/// Returns a four-character-code identifier from `b` at `i`. pub fn ident(b: &[u8]) -> Ident
pub fn c_iden(b: &[u8], i: usize) -> ResultS<Ident>
{ {
ok!(o_iden(b, i), "not enough data") [b[0], b[1], b[2], b[3]]
} }
/// Returns a big-endian `u32` from `b` at `i`. pub fn u32b(b: &[u8]) -> u32
pub fn c_u32b(b: &[u8], i: usize) -> ResultS<u32>
{ {
ok!(o_u32b(b, i), "not enough data") u32::from_be_bytes([b[0], b[1], b[2], b[3]])
} }
/// Returns a big-endian `u16` from `b` at `i`. pub fn u16b(b: &[u8]) -> u16
pub fn c_u16b(b: &[u8], i: usize) -> ResultS<u16>
{ {
ok!(o_u16b(b, i), "not enough data") u16::from_be_bytes([b[0], b[1]])
} }
/// Returns a big-endian `i32` from `b` at `i`. pub fn i32b(b: &[u8]) -> i32
pub fn c_i32b(b: &[u8], i: usize) -> ResultS<i32>
{ {
ok!(o_i32b(b, i), "not enough data") i32::from_be_bytes([b[0], b[1], b[2], b[3]])
} }
/// Returns a big-endian `i16` from `b` at `i`. pub fn i16b(b: &[u8]) -> i16
pub fn c_i16b(b: &[u8], i: usize) -> ResultS<i16>
{ {
ok!(o_i16b(b, i), "not enough data") i16::from_be_bytes([b[0], b[1]])
} }
/// Returns a four-character-code identifier from `b` at `i`. pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
pub fn o_iden(b: &[u8], i: usize) -> Option<Ident>
{
if i + 3 < b.len() {
Some([b[i], b[i + 1], b[i + 2], b[i + 3]])
} else {
None
}
}
/// Returns a big-endian `u32` from `b` at `i`.
pub fn o_u32b(b: &[u8], i: usize) -> Option<u32>
{
if i + 3 < b.len() {
Some(u32::from_be_bytes([b[i], b[i + 1], b[i + 2], b[i + 3]]))
} else {
None
}
}
/// Returns a big-endian `i32` from `b` at `i`.
pub fn o_i32b(b: &[u8], i: usize) -> Option<i32>
{
if i + 3 < b.len() {
Some(i32::from_be_bytes([b[i], b[i + 1], b[i + 2], b[i + 3]]))
} else {
None
}
}
/// Returns a big-endian `u16` from `b` at `i`.
pub fn o_u16b(b: &[u8], i: usize) -> Option<u16>
{
if i + 1 < b.len() {
Some(u16::from_be_bytes([b[i], b[i + 1]]))
} else {
None
}
}
/// Returns a big-endian `i16` from `b` at `i`.
pub fn o_i16b(b: &[u8], i: usize) -> Option<i16>
{
if i + 1 < b.len() {
Some(i16::from_be_bytes([b[i], b[i + 1]]))
} else {
None
}
}
/// Reads an array of any type.
pub fn c_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
where T: Sized, where T: Sized,
F: Fn(&[u8]) -> ResultS<(T, usize)> F: Fn(&[u8]) -> ResultS<(T, usize)>
{ {
@ -117,6 +133,30 @@ pub fn c_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
Ok(v) Ok(v)
} }
pub fn rd_ofstable<T, F>(b: &[u8],
mut p: usize,
num: usize,
read: F)
-> ResultS<Vec<T>>
where T: Sized,
F: Fn(&[u8]) -> ResultS<T>
{
let mut v = Vec::with_capacity(num);
for _ in 0..num {
let ofs = u32b(&b[p..]) as usize;
if ofs >= b.len() {
bail!("not enough data");
}
v.push(read(&b[ofs..])?);
p += 4;
}
Ok(v)
}
impl ObjID impl ObjID
{ {
/// Creates an `ObjID` from a `u16`. /// Creates an `ObjID` from a `u16`.

View File

@ -1,11 +1,12 @@
//! Library for various utilities. //! Library for various utilities.
#[macro_use]
pub mod err;
#[macro_use] #[macro_use]
pub mod cenum; pub mod cenum;
#[macro_use] #[macro_use]
pub mod err;
pub mod bin; pub mod bin;
pub mod crc; pub mod crc;
pub mod file; pub mod file;
pub mod fixed; pub mod fixed;

View File

@ -51,12 +51,12 @@ fn dump_chunk(opt: &Options, cid: Ident, cnk: &[u8], eid: u16) -> ResultS<()>
make_tga(&format!("{}/pict_{}.tga", opt.out_dir, eid), &im)?; make_tga(&format!("{}/pict_{}.tga", opt.out_dir, eid), &im)?;
} }
b"Minf" => make_yaml(opt, &map::read_minf(cnk)?)?, b"Minf" => make_yaml(opt, &map::read_minf(cnk)?)?,
b"EPNT" => make_yaml(opt, &c_array(cnk, map::read_epnt)?)?, b"EPNT" => make_yaml(opt, &rd_array(cnk, map::read_epnt)?)?,
b"PNTS" => make_yaml(opt, &c_array(cnk, map::read_pnts)?)?, b"PNTS" => make_yaml(opt, &rd_array(cnk, map::read_pnts)?)?,
b"LINS" => make_yaml(opt, &c_array(cnk, map::read_lins)?)?, b"LINS" => make_yaml(opt, &rd_array(cnk, map::read_lins)?)?,
b"SIDS" => make_yaml(opt, &c_array(cnk, map::read_sids)?)?, b"SIDS" => make_yaml(opt, &rd_array(cnk, map::read_sids)?)?,
b"POLY" => make_yaml(opt, &c_array(cnk, map::read_poly)?)?, b"POLY" => make_yaml(opt, &rd_array(cnk, map::read_poly)?)?,
b"term" => make_yaml(opt, &c_array(cnk, trm::read_term)?)?, b"term" => make_yaml(opt, &rd_array(cnk, trm::read_term)?)?,
_ => (), _ => (),
} }
} }
@ -183,7 +183,7 @@ fn main() -> ResultS<()>
macro_rules! arg { macro_rules! arg {
($name:expr, $ref:expr, $type:expr, $ap:expr, $desc:expr) => { ($name:expr, $ref:expr, $type:expr, $ap:expr, $desc:expr) => {
$ap.refer(&mut $ref).add_option(&[$name], $type, $desc); $ap.refer(&mut $ref).add_option(&[$name], $type, $desc);
} };
} }
let mut ap = ArgumentParser::new(); let mut ap = ArgumentParser::new();
@ -250,7 +250,7 @@ fn main() -> ResultS<()>
if !opt.wad_c_temp.is_empty() { if !opt.wad_c_temp.is_empty() {
for ctyp in opt.wad_c_temp.split(',') { for ctyp in opt.wad_c_temp.split(',') {
opt.wad_chunks.insert(c_iden(ctyp.as_bytes(), 0)?); opt.wad_chunks.insert(ident(ctyp.as_bytes()));
} }
} }
@ -265,7 +265,7 @@ fn main() -> ResultS<()>
let fp = fs::File::open(fna)?; let fp = fs::File::open(fna)?;
let mm = unsafe {Mmap::map(&fp)?}; let mm = unsafe {Mmap::map(&fp)?};
let b = c_data(&mm, machdr::try_mac_header(&mm)..)?; let b = &mm[machdr::try_mac_header(&mm)..];
match typ { match typ {
"wad:" => process_wad(&opt, b), "wad:" => process_wad(&opt, b),

View File

@ -6,17 +6,22 @@ use crate::durandal::bin::*;
pub fn check_apple_single(b: &[u8]) -> Option<usize> pub fn check_apple_single(b: &[u8]) -> Option<usize>
{ {
// check magic numbers // check magic numbers
if *b.get(0..8)? != [0, 5, 22, 0, 0, 2, 0, 0] { if b.len() < 26 || *b.get(0..8)? != [0, 5, 22, 0, 0, 2, 0, 0] {
return None;
}
let num = u16b(&b[24..]) as usize;
if b.len() < 26 + 12 * num {
return None; return None;
} }
// get the resource fork (entity 1) // get the resource fork (entity 1)
let num = o_u16b(b, 24)? as usize;
for i in 0..num { for i in 0..num {
let p = 26 + 12 * i; let p = 26 + 12 * i;
let ent = o_u32b(b, p)?; let ent = u32b(&b[p..]);
let ofs = o_u32b(b, p + 4)? as usize; let ofs = u32b(&b[p + 4..]) as usize;
let len = o_u32b(b, p + 8)? as usize; let len = u32b(&b[p + 8..]) as usize;
if ent == 1 { if ent == 1 {
return if ofs + len > b.len() {None} else {Some(ofs)}; return if ofs + len > b.len() {None} else {Some(ofs)};
@ -50,7 +55,7 @@ pub fn check_macbin(b: &[u8]) -> Option<usize>
} }
// if ok, resource fork follows // if ok, resource fork follows
if crc == o_u16b(b, 124)? { if crc == u16b(&b[124..]) {
Some(128) Some(128)
} else { } else {
None None

View File

@ -7,13 +7,17 @@ use std::fmt;
pub fn read_minf(b: &[u8]) -> ResultS<Minf> pub fn read_minf(b: &[u8]) -> ResultS<Minf>
{ {
let env_code = c_u16b(b, 0)?; read_data! {
let physi_id = c_u16b(b, 2)?; 88, BE in b =>
let music_id = c_u16b(b, 4)?; env_code = u16[0];
let msn_flag = c_u16b(b, 6)?; physi_id = u16[2];
let env_flag = c_u16b(b, 8)?; music_id = u16[4];
let levelnam = mac_roman_conv(c_data(b, 18..84)?); msn_flag = u16[6];
let ent_flag = c_u32b(b, 84)?; env_flag = u16[8];
levelnam = mac_roman_conv[18..84] nt;
ent_flag = u32[84];
}
let msn_flag = ok!(MsnFlags::from_bits(msn_flag), "bad MsnFlags")?; let msn_flag = ok!(MsnFlags::from_bits(msn_flag), "bad MsnFlags")?;
let env_flag = ok!(EnvFlags::from_bits(env_flag), "bad EnvFlags")?; let env_flag = ok!(EnvFlags::from_bits(env_flag), "bad EnvFlags")?;
let ent_flag = ok!(EntFlags::from_bits(ent_flag), "bad EntFlags")?; let ent_flag = ok!(EntFlags::from_bits(ent_flag), "bad EntFlags")?;
@ -23,24 +27,36 @@ pub fn read_minf(b: &[u8]) -> ResultS<Minf>
pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex> pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex>
{ {
let offs = read_point(c_data(b, 0..4)?)?; read_data! {
let tex_id = c_u16b(b, 4)?; 6, BE in b =>
offs = read_point[0..4];
tex_id = u16[4];
}
let tex_id = ObjID::from_repr(tex_id); let tex_id = ObjID::from_repr(tex_id);
Ok(SideTex{offs, tex_id}) Ok(SideTex{offs, tex_id})
} }
pub fn read_point(b: &[u8]) -> ResultS<Point> pub fn read_point(b: &[u8]) -> ResultS<Point>
{ {
let x = c_u16b(b, 0)?; read_data! {
let y = c_u16b(b, 2)?; 4, BE in b =>
let x = Unit::from_bits(x); x = u16[0];
let y = Unit::from_bits(y); y = u16[2];
Ok(Point{x, y}) }
Ok(Point{x: Unit::from_bits(x), y: Unit::from_bits(y)})
} }
pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)> pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)>
{ {
Ok((read_point(c_data(b, 6..10)?)?, 16)) read_data! {
16, BE in b =>
pnt = read_point[6..10];
}
Ok((pnt, 16))
} }
pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)> pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)>
@ -50,79 +66,92 @@ pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)>
pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)> pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)>
{ {
let pnt_beg = c_u16b(b, 0)?; read_data! {
let pnt_end = c_u16b(b, 2)?; 32, BE in b =>
let flags = c_u16b(b, 4)?; pnt_beg = u16[0];
let side_fr = c_u16b(b, 12)?; pnt_end = u16[2];
let side_bk = c_u16b(b, 14)?; flags = u16[4];
let poly_fr = c_u16b(b, 16)?; side_fr = u16[12];
let poly_bk = c_u16b(b, 18)?; side_bk = u16[14];
poly_fr = u16[16];
poly_bk = u16[18];
}
let flags = ok!(LineFlags::from_bits(flags), "bad LineFlags")?; let flags = ok!(LineFlags::from_bits(flags), "bad LineFlags")?;
let side_fr = ObjID::from_repr(side_fr); let side_fr = ObjID::from_repr(side_fr);
let side_bk = ObjID::from_repr(side_bk); let side_bk = ObjID::from_repr(side_bk);
let poly_fr = ObjID::from_repr(poly_fr); let poly_fr = ObjID::from_repr(poly_fr);
let poly_bk = ObjID::from_repr(poly_bk); let poly_bk = ObjID::from_repr(poly_bk);
Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32)) Ok((Line{flags, pnt_beg, pnt_end, side_fr, side_bk, poly_fr, poly_bk}, 32))
} }
pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)> pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)>
{ {
let stype = c_u16b(b, 0)?; read_data! {
let flags = c_u16b(b, 2)?; 64, BE in b =>
let tex_pri = read_sidetex(c_data(b, 4..10)?)?; stype = u16[0];
let tex_sec = read_sidetex(c_data(b, 10..16)?)?; flags = u16[2];
let tex_tra = read_sidetex(c_data(b, 16..22)?)?; tex_pri = read_sidetex[4..10];
let paneltyp = c_u16b(b, 38)?; tex_sec = read_sidetex[10..16];
let paneldat = c_i16b(b, 40)?; tex_tra = read_sidetex[16..22];
let xfer_pri = c_u16b(b, 42)?; paneltyp = u16[38];
let xfer_sec = c_u16b(b, 44)?; paneldat = i16[40];
let xfer_tra = c_u16b(b, 46)?; xfer_pri = u16[42];
let shade = c_u32b(b, 48)?; xfer_sec = u16[44];
let stype = SideType::from_repr(stype)?; xfer_tra = u16[46];
shade = u32[48];
}
let flags = ok!(SideFlags::from_bits(flags), "bad SideFlags")?; let flags = ok!(SideFlags::from_bits(flags), "bad SideFlags")?;
let xfer_pri = TransferMode::from_repr(xfer_pri)?; let xfer_pri = TransferMode::from_repr(xfer_pri)?;
let xfer_sec = TransferMode::from_repr(xfer_sec)?; let xfer_sec = TransferMode::from_repr(xfer_sec)?;
let xfer_tra = TransferMode::from_repr(xfer_tra)?; let xfer_tra = TransferMode::from_repr(xfer_tra)?;
let stype = SideType::from_repr(stype)?;
let shade = Fixed::from_bits(shade); let shade = Fixed::from_bits(shade);
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat, Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, paneltyp, paneldat,
xfer_pri, xfer_sec, xfer_tra, shade}, 64)) xfer_pri, xfer_sec, xfer_tra, shade}, 64))
} }
pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)> pub fn read_poly(b: &[u8]) -> ResultS<(Polygon, usize)>
{ {
let ptype = c_u16b(b, 0)?; read_data! {
let flags = c_u16b(b, 2)?; 128, BE in b =>
let pdata = c_i16b(b, 4)?; ptype = u16[0];
let tex_flr = c_u16b(b, 40)?; flags = u16[2];
let tex_cei = c_u16b(b, 42)?; pdata = i16[4];
let hei_flr = c_u16b(b, 44)?; tex_flr = u16[40];
let hei_cei = c_u16b(b, 46)?; tex_cei = u16[42];
let lit_flr = c_u16b(b, 48)?; hei_flr = u16[44];
let lit_cei = c_u16b(b, 50)?; hei_cei = u16[46];
let xfr_flr = c_u16b(b, 64)?; lit_flr = u16[48];
let xfr_cei = c_u16b(b, 66)?; lit_cei = u16[50];
let ori_flr = read_point(c_data(b, 108..112)?)?; xfr_flr = u16[64];
let ori_cei = read_point(c_data(b, 112..116)?)?; xfr_cei = u16[66];
let media = c_u16b(b, 116)?; ori_flr = read_point[108..112];
let media_l = c_u16b(b, 118)?; ori_cei = read_point[112..116];
let sound = c_u16b(b, 120)?; media = u16[116];
let snd_amb = c_u16b(b, 122)?; media_l = u16[118];
let snd_rnd = c_u16b(b, 124)?; sound = u16[120];
let ptype = PolyType::from_repr(ptype)?; snd_amb = u16[122];
snd_rnd = u16[124];
}
let flags = ok!(PolyFlags::from_bits(flags), "bad PolyFlags")?; let flags = ok!(PolyFlags::from_bits(flags), "bad PolyFlags")?;
let tex_flr = ObjID::from_repr(tex_flr);
let tex_cei = ObjID::from_repr(tex_cei);
let hei_flr = Unit::from_bits(hei_flr);
let hei_cei = Unit::from_bits(hei_cei);
let xfr_flr = TransferMode::from_repr(xfr_flr)?; let xfr_flr = TransferMode::from_repr(xfr_flr)?;
let xfr_cei = TransferMode::from_repr(xfr_cei)?; let xfr_cei = TransferMode::from_repr(xfr_cei)?;
let ptype = PolyType::from_repr(ptype)?;
let tex_flr = ObjID::from_repr(tex_flr);
let tex_cei = ObjID::from_repr(tex_cei);
let snd_amb = ObjID::from_repr(snd_amb); let snd_amb = ObjID::from_repr(snd_amb);
let snd_rnd = ObjID::from_repr(snd_rnd); let snd_rnd = ObjID::from_repr(snd_rnd);
let hei_flr = Unit::from_bits(hei_flr);
let hei_cei = Unit::from_bits(hei_cei);
Ok((Polygon{ptype, flags, pdata, tex_flr, tex_cei, hei_flr, hei_cei, Ok((Polygon{ptype, flags, pdata, tex_flr, tex_cei, hei_flr, hei_cei,
lit_flr, lit_cei, xfr_flr, xfr_cei, ori_flr, ori_cei, media, lit_flr, lit_cei, xfr_flr, xfr_cei, ori_flr, ori_cei, media,
media_l, sound, snd_amb, snd_rnd}, media_l, sound, snd_amb, snd_rnd}, 128))
128))
} }
#[derive(Serialize)] #[derive(Serialize)]

View File

@ -10,13 +10,17 @@ fn read_pm_header<'a>(b: &'a [u8],
im: &Image8) im: &Image8)
-> ResultS<(&'a [u8], Header)> -> ResultS<(&'a [u8], Header)>
{ {
let pt_fl = c_u16b(b, 0)?; read_data! {
let top = c_u16b(b, 2)? as usize; 36, BE in b =>
let left = c_u16b(b, 4)? as usize; pt_fl = u16[0];
let bottom = c_u16b(b, 6)? as usize; top = u16[2] as usize;
let right = c_u16b(b, 8)? as usize; left = u16[4] as usize;
let pack_t = c_u16b(b, 12)?; bottom = u16[6] as usize;
let depth = c_u16b(b, 28)?; right = u16[8] as usize;
pack_t = u16[12];
depth = u16[28];
}
let pack_t = PackType::from_repr(pack_t)?; let pack_t = PackType::from_repr(pack_t)?;
if pt_fl & 0x8000 == 0 { if pt_fl & 0x8000 == 0 {
@ -31,7 +35,7 @@ fn read_pm_header<'a>(b: &'a [u8],
// get CLUT if packed // get CLUT if packed
let clut = if pack { let clut = if pack {
let (clut, sz) = get_clut(c_data(b, p..)?)?; let (clut, sz) = get_clut(&b[p..])?;
p += sz; p += sz;
Some(clut) Some(clut)
} else { } else {
@ -41,7 +45,7 @@ fn read_pm_header<'a>(b: &'a [u8],
p += 18; // srcRect, dstRect, mode p += 18; // srcRect, dstRect, mode
if clip { if clip {
p += c_u16b(b, p)? as usize; // maskRgn p += u16b(&b[p..]) as usize; // maskRgn
} }
let rle = pack_t == PackType::Default || let rle = pack_t == PackType::Default ||
@ -63,7 +67,7 @@ fn read_pm_ind(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
// uncompressed 8-bit colormap indices // uncompressed 8-bit colormap indices
for _ in 0..im.h() { for _ in 0..im.h() {
for _ in 0..im.w() { for _ in 0..im.w() {
let idx = c_byte(b, p)? as usize; let idx = b[p] as usize;
im.cr.push(ok!(clut.get(idx), "invalid index")?.clone()); im.cr.push(ok!(clut.get(idx), "invalid index")?.clone());
p += 1; p += 1;
} }
@ -73,13 +77,13 @@ fn read_pm_ind(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
} else if hdr.rle { } else if hdr.rle {
// RLE compressed 1, 2, 4 or 8 bit colormap indices // RLE compressed 1, 2, 4 or 8 bit colormap indices
for _ in 0..im.h() { for _ in 0..im.h() {
let (d, pp) = read_rle(c_data(b, p..)?, hdr.pitch, false)?; let (d, pp) = read_rle(&b[p..], hdr.pitch, false)?;
let d = if hdr.depth < 8 {expand_data(d, hdr.depth)?} else {d}; let d = if hdr.depth < 8 {expand_data(d, hdr.depth)?} else {d};
p += pp; p += pp;
for x in 0..im.w() { for x in 0..im.w() {
let idx = c_byte(&d, x)? as usize; let idx = d[x] as usize;
im.cr.push(ok!(clut.get(idx), "invalid index")?.clone()); im.cr.push(ok!(clut.get(idx), "invalid index")?.clone());
} }
} }
@ -99,7 +103,8 @@ fn read_pm_16(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
// uncompressed R5G5B5 // uncompressed R5G5B5
for _ in 0..im.h() { for _ in 0..im.h() {
for _ in 0..im.w() { for _ in 0..im.w() {
im.cr.push(r5g5b5_to_rgb8(c_u16b(b, p)?)); let cr = u16b(&b[p..]);
im.cr.push(r5g5b5_to_rgb8(cr));
p += 2; p += 2;
} }
} }
@ -108,12 +113,13 @@ fn read_pm_16(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
} else if hdr.rle { } else if hdr.rle {
// RLE compressed R5G5B5 // RLE compressed R5G5B5
for _ in 0..im.h() { for _ in 0..im.h() {
let (d, pp) = read_rle(c_data(b, p..)?, hdr.pitch, true)?; let (d, pp) = read_rle(&b[p..], hdr.pitch, true)?;
p += pp; p += pp;
for x in 0..im.w() { for x in 0..im.w() {
im.cr.push(r5g5b5_to_rgb8(c_u16b(&d, x * 2)?)); let cr = u16b(&d[x * 2..]);
im.cr.push(r5g5b5_to_rgb8(cr));
} }
} }
@ -135,11 +141,17 @@ fn read_pm_32(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
if hdr.pack_t != PackType::NoPad { if hdr.pack_t != PackType::NoPad {
p += 1; p += 1;
} }
let r = c_byte(b, p)?;
let g = c_byte(b, p + 1)?; read_data! {
let b = c_byte(b, p + 2)?; p + 3, BE in b =>
p += 3; r = u8[p];
g = u8[p + 1];
b = u8[p + 2];
}
im.cr.push(Color8::new(r, g, b)); im.cr.push(Color8::new(r, g, b));
p += 3;
} }
} }
@ -148,14 +160,14 @@ fn read_pm_32(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
// RLE compressed RGB8 // RLE compressed RGB8
let pitch = hdr.pitch - im.w(); // remove padding byte from pitch let pitch = hdr.pitch - im.w(); // remove padding byte from pitch
for _ in 0..im.h() { for _ in 0..im.h() {
let (d, pp) = read_rle(c_data(b, p..)?, pitch, false)?; let (d, pp) = read_rle(&b[p..], pitch, false)?;
p += pp; p += pp;
for x in 0..im.w() { for x in 0..im.w() {
let r = c_byte(&d, x + im.w())?; let r = d[x + im.w()];
let g = c_byte(&d, x + im.w() * 2)?; let g = d[x + im.w() * 2];
let b = c_byte(&d, x + im.w() * 3)?; let b = d[x + im.w() * 3];
im.cr.push(Color8::new(r, g, b)); im.cr.push(Color8::new(r, g, b));
} }
} }
@ -193,36 +205,44 @@ fn read_quicktime_c(_im: Image8, _b: &[u8]) -> ResultS<Image8>
/// Load a PICT image. /// Load a PICT image.
pub fn load_pict(b: &[u8]) -> ResultS<Image8> pub fn load_pict(b: &[u8]) -> ResultS<Image8>
{ {
let h = c_u16b(b, 6)? as usize; read_data! {
let w = c_u16b(b, 8)? as usize; 10, BE in b =>
h = u16[6] as usize;
w = u16[8] as usize;
}
let im = Image8::new(w, h); let im = Image8::new(w, h);
let mut p = 10; // size of header let mut p = 10; // size of header
while p < b.len() { while p < b.len() {
let op = c_u16b(b, p)?; read_data! {
p + 2, BE in b =>
op = u16[p];
}
p += 2; p += 2;
match op { match op {
0x0098 => { 0x0098 => {
// PackBitsRect // PackBitsRect
return read_pm_area(im, c_data(b, p..)?, true, false); return read_pm_area(im, &b[p..], true, false);
} }
0x0099 => { 0x0099 => {
// PackBitsRgn // PackBitsRgn
return read_pm_area(im, c_data(b, p..)?, true, true); return read_pm_area(im, &b[p..], true, true);
} }
0x009a => { 0x009a => {
// DirectBitsRect // DirectBitsRect
return read_pm_area(im, c_data(b, p..)?, false, false); return read_pm_area(im, &b[p..], false, false);
} }
0x009b => { 0x009b => {
// DirectBitsRgn // DirectBitsRgn
return read_pm_area(im, c_data(b, p..)?, false, true); return read_pm_area(im, &b[p..], false, true);
} }
0x8200 => { 0x8200 => {
// CompressedQuickTime // CompressedQuickTime
return read_quicktime_c(im, c_data(b, p..)?); return read_quicktime_c(im, &b[p..]);
} }
0x00ff => { 0x00ff => {
// OpEndPic // OpEndPic
@ -271,8 +291,8 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
0x0033 | // InvertRect 0x0033 | // InvertRect
0x0034 => p += 8, // FillRect 0x0034 => p += 8, // FillRect
0x002d => p += 10, // LineJustify 0x002d => p += 10, // LineJustify
0x0001 => p += (c_u16b(b, p )? & !1) as usize, // Clip 0x0001 => p += (u16b(&b[p.. ]) & !1) as usize, // Clip
0x00a1 => p += (c_u16b(b, p+2)? & !1) as usize + 2, // LongComment 0x00a1 => p += (u16b(&b[p+2..]) & !1) as usize + 2, // LongComment
0x100..= 0x100..=
0x7fff => p += (op >> 8) as usize * 2, // Reserved 0x7fff => p += (op >> 8) as usize * 2, // Reserved
_ => { _ => {
@ -287,23 +307,30 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
/// Read a colorTable structure. /// Read a colorTable structure.
pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)> pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
{ {
let dev = c_u16b(b, 4)? & 0x8000 != 0; read_data! {
let num = c_u16b(b, 6)? as usize + 1; 8, BE in b =>
dev = u16[4];
num = u16[6] as usize;
}
let dev = dev & 0x8000 != 0;
let num = num + 1;
let mut p = 8; let mut p = 8;
let mut clut = vec![Color8::new(0, 0, 0); num]; let mut clut = vec![Color8::new(0, 0, 0); num];
for i in 0..num { for i in 0..num {
// with device mapping, we ignore the index entirely read_data! {
let n = if !dev {c_u16b(b, p)? as usize} else {i}; p + 8, BE in b =>
let r = c_byte(b, p + 2)?; n = u16[p] as usize;
let g = c_byte(b, p + 4)?; r = u8[p + 2];
let b = c_byte(b, p + 6)?; g = u8[p + 4];
b = u8[p + 6];
if n >= clut.len() {
bail!("bad clut index");
} }
// with device mapping, we ignore the index entirely
let n = if !dev {n} else {i};
*ok!(clut.get_mut(n), "invalid index")? = Color8::new(r, g, b); *ok!(clut.get_mut(n), "invalid index")? = Color8::new(r, g, b);
p += 8; p += 8;
@ -319,13 +346,13 @@ pub fn read_rle(b: &[u8], pitch: usize, ln: bool) -> ResultS<(Vec<u8>, usize)>
let mut o = Vec::with_capacity(pitch); let mut o = Vec::with_capacity(pitch);
let sz = if pitch > 250 { let sz = if pitch > 250 {
(c_u16b(b, 0)? as usize + 2, p += 2).0 (u16b(b) as usize + 2, p += 2).0
} else { } else {
(c_byte(b, 0)? as usize + 1, p += 1).0 (b[0] as usize + 1, p += 1).0
}; };
while p < sz { while p < sz {
let szf = c_byte(b, p)?; let szf = b[p];
let cmp = szf & 0x80 != 0; let cmp = szf & 0x80 != 0;
let len = if cmp {!szf + 2} else {szf + 1} as usize; let len = if cmp {!szf + 2} else {szf + 1} as usize;

View File

@ -5,49 +5,72 @@ use crate::{durandal::{bin::*, err::*, fixed::*, image::*, text::*},
use bitflags::bitflags; use bitflags::bitflags;
use serde::Serialize; use serde::Serialize;
fn color(b: &[u8]) -> ResultS<(usize, ColorShp)> fn color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
{ {
let l = c_byte(b, 0)?; read_data! {
let i = c_byte(b, 1)? as usize; 8, BE in b =>
let r = c_u16b(b, 2)?; l = u8[0];
let g = c_u16b(b, 4)?; i = u8[1];
let b = c_u16b(b, 6)?; r = u16[2];
g = u16[4];
b = u16[6];
}
let l = match l { let l = match l {
128 => Ok(true), 128 => Ok(true),
0 => Ok(false), 0 => Ok(false),
_ => Err(err_msg("invalid flag in color")), _ => Err(err_msg("invalid flag in color")),
}?; }?;
Ok((i, ColorShp::Opaque{r, g, b, l})) let cr = ColorShp::Opaque{r, g, b, l};
if let Some(cl) = clut.get_mut(i as usize) {
*cl = cr;
Ok(())
} else {
bail!("bad index");
}
} }
fn tab_coll(b: &[u8], fn color_tables(b: &[u8],
tab_ofs: usize,
tab_num: usize, tab_num: usize,
clr_num: usize) clr_num: usize)
-> ResultS<Vec<Vec<ColorShp>>> -> ResultS<Vec<Vec<ColorShp>>>
{ {
let mut tabs = vec![vec![ColorShp::Translucent; clr_num]; tab_num]; let end = tab_num * clr_num * 8;
if b.len() < tab_ofs + end {
bail!("not enough data");
}
let b = &b[tab_ofs..tab_ofs + end];
let mut v = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
let mut p = 0; let mut p = 0;
for clut in tabs.iter_mut().take(tab_num) { for clut in v.iter_mut().take(tab_num) {
for _ in 0..clr_num { for _ in 0..clr_num {
let (i, cr) = color(c_data(b, p..)?)?; color(&b[p..p + 8], clut)?;
*ok!(clut.get_mut(i), "invalid index")? = cr;
p += 8; p += 8;
} }
} }
Ok(tabs) Ok(v)
} }
fn bitmap(b: &[u8]) -> ResultS<Bitmap> fn bitmap(b: &[u8]) -> ResultS<Bitmap>
{ {
let width = c_u16b(b, 0)? as usize; read_data! {
let height = c_u16b(b, 2)? as usize; 26, BE in b =>
let compr = c_u16b(b, 4)? == u16::max_value(); width = u16[0] as usize;
let flags = c_u16b(b, 6)?; height = u16[2] as usize;
let depth = c_u16b(b, 8)?; compr = u16[4];
flags = u16[6];
depth = u16[8];
}
let compr = compr == u16::max_value();
let flags = ok!(BmpFlags::from_bits(flags), "bad BmpFlags")?; let flags = ok!(BmpFlags::from_bits(flags), "bad BmpFlags")?;
let alpha = flags.contains(BmpFlags::Transparent); let alpha = flags.contains(BmpFlags::Transparent);
let cmajr = flags.contains(BmpFlags::ColumnMajor); let cmajr = flags.contains(BmpFlags::ColumnMajor);
@ -65,21 +88,24 @@ fn bitmap(b: &[u8]) -> ResultS<Bitmap>
if compr { if compr {
// compressed scanlines (transparency RLE) // compressed scanlines (transparency RLE)
for _ in 0..scanlines { for _ in 0..scanlines {
let fst = c_u16b(b, p)? as usize; read_data! {
let lst = c_u16b(b, p + 2)? as usize; p + 4, BE in b =>
fst = u16[p] as usize;
if lst < fst || fst > pitch || lst > pitch { lst = u16[p + 2] as usize;
bail!("invalid compressed scanline");
} }
let end = lst - fst;
p += 4; p += 4;
if lst < fst || fst > pitch || lst > pitch || p + end >= b.len() {
bail!("invalid compressed scanline");
}
for _ in 0..fst { for _ in 0..fst {
bmp.cr.push(0); bmp.cr.push(0);
} }
let end = lst - fst; bmp.cr.extend_from_slice(&b[p..p + end]);
bmp.cr.extend_from_slice(c_data(b, p..p + end)?);
for _ in lst..pitch { for _ in lst..pitch {
bmp.cr.push(0); bmp.cr.push(0);
@ -89,37 +115,31 @@ fn bitmap(b: &[u8]) -> ResultS<Bitmap>
} }
} else { } else {
// simple copy // simple copy
bmp.cr.extend_from_slice(c_data(b, p..p + width * height)?); if p + width * height >= b.len() {
bail!("invalid scanline");
}
bmp.cr.extend_from_slice(&b[p..p + width * height]);
} }
Ok(bmp) Ok(bmp)
} }
fn bmp_coll(b: &[u8], ofs: usize, num: usize) -> ResultS<Vec<Bitmap>>
{
let mut bmps = Vec::with_capacity(num);
let mut p = ofs;
for _ in 0..num {
let ofs = c_u32b(b, p)? as usize;
bmps.push(bitmap(c_data(b, ofs..)?)?);
p += 4;
}
Ok(bmps)
}
fn frame(b: &[u8]) -> ResultS<Frame> fn frame(b: &[u8]) -> ResultS<Frame>
{ {
let flags = c_u16b(b, 0)?; read_data! {
let min_lt = c_u32b(b, 2)?; 36, BE in b =>
let bmp_ind = c_u16b(b, 6)? as usize; flags = u16[0];
let wrl_l = c_u16b(b, 16)?; min_lt = u32[2];
let wrl_r = c_u16b(b, 18)?; bmp_ind = u16[6] as usize;
let wrl_t = c_u16b(b, 20)?; wrl_l = u16[16];
let wrl_b = c_u16b(b, 22)?; wrl_r = u16[18];
let wrl_x = c_u16b(b, 24)?; wrl_t = u16[20];
let wrl_y = c_u16b(b, 26)?; wrl_b = u16[22];
wrl_x = u16[24];
wrl_y = u16[26];
}
let flags = ok!(FrameFlags::from_bits(flags), "bad flag")?; let flags = ok!(FrameFlags::from_bits(flags), "bad flag")?;
let min_lt = Fixed::from_bits(min_lt); let min_lt = Fixed::from_bits(min_lt);
let wrl_l = Unit::from_bits(wrl_l); let wrl_l = Unit::from_bits(wrl_l);
@ -132,36 +152,26 @@ fn frame(b: &[u8]) -> ResultS<Frame>
Ok(Frame{flags, min_lt, bmp_ind, wrl_l, wrl_r, wrl_t, wrl_b, wrl_x, wrl_y}) Ok(Frame{flags, min_lt, bmp_ind, wrl_l, wrl_r, wrl_t, wrl_b, wrl_x, wrl_y})
} }
fn frm_coll(b: &[u8], ofs: usize, num: usize) -> ResultS<Vec<Frame>>
{
let mut frms = Vec::with_capacity(num);
let mut p = ofs;
for _ in 0..num {
let ofs = c_u32b(b, p)? as usize;
frms.push(frame(c_data(b, ofs..)?)?);
p += 4;
}
Ok(frms)
}
fn sequence(b: &[u8]) -> ResultS<Sequence> fn sequence(b: &[u8]) -> ResultS<Sequence>
{ {
let name = c_data(b, 4..38)?; read_data! {
let v_type = c_u16b(b, 38)?; 88, BE in b =>
let frames = c_u16b(b, 40)?; name = u8[4..38] array;
let ticks = c_u16b(b, 42)?; v_type = u16[38];
let key = c_u16b(b, 44)?; frames = u16[40];
let xfer = c_u16b(b, 46)?; ticks = u16[42];
let xfer_pd = c_u16b(b, 48)?; key = u16[44];
let snd_beg = c_u16b(b, 50)?; xfer = u16[46];
let snd_key = c_u16b(b, 52)?; xfer_pd = u16[48];
let snd_end = c_u16b(b, 54)?; snd_beg = u16[50];
let loop_f = c_u16b(b, 58)?; snd_key = u16[52];
snd_end = u16[54];
loop_f = u16[58];
}
let name = mac_roman_conv(ok!(pascal_str(name), "bad string")?); let name = mac_roman_conv(ok!(pascal_str(name), "bad string")?);
let v_type = ViewType::from_repr(v_type)?;
let xfer = TransferMode::from_repr(xfer)?; let xfer = TransferMode::from_repr(xfer)?;
let v_type = ViewType::from_repr(v_type)?;
let snd_beg = ObjID::from_repr(snd_beg); let snd_beg = ObjID::from_repr(snd_beg);
let snd_key = ObjID::from_repr(snd_key); let snd_key = ObjID::from_repr(snd_key);
let snd_end = ObjID::from_repr(snd_end); let snd_end = ObjID::from_repr(snd_end);
@ -170,43 +180,33 @@ fn sequence(b: &[u8]) -> ResultS<Sequence>
snd_key, snd_end, loop_f}) snd_key, snd_end, loop_f})
} }
fn seq_coll(b: &[u8], ofs: usize, num: usize) -> ResultS<Vec<Sequence>>
{
let mut seqs = Vec::with_capacity(num);
let mut p = ofs;
for _ in 0..num {
let ofs = c_u32b(b, p)? as usize;
seqs.push(sequence(c_data(b, ofs..)?)?);
p += 4;
}
Ok(seqs)
}
fn collection(b: &[u8]) -> ResultS<Collection> fn collection(b: &[u8]) -> ResultS<Collection>
{ {
let version = c_u16b(b, 0)?; read_data! {
let cl_type = c_u16b(b, 2)?; 544, BE in b =>
let clr_num = c_u16b(b, 6)? as usize; version = u16[0];
let tab_num = c_u16b(b, 8)? as usize; cl_type = u16[2];
let tab_ofs = c_u32b(b, 10)? as usize; clr_num = u16[6] as usize;
let seq_num = c_u16b(b, 14)? as usize; tab_num = u16[8] as usize;
let seq_ofs = c_u32b(b, 16)? as usize; tab_ofs = u32[10] as usize;
let frm_num = c_u16b(b, 20)? as usize; seq_num = u16[14] as usize;
let frm_ofs = c_u32b(b, 22)? as usize; seq_ofs = u32[16] as usize;
let bmp_num = c_u16b(b, 26)? as usize; frm_num = u16[20] as usize;
let bmp_ofs = c_u32b(b, 28)? as usize; frm_ofs = u32[22] as usize;
bmp_num = u16[26] as usize;
bmp_ofs = u32[28] as usize;
}
let cl_type = CollectionType::from_repr(cl_type)?; let cl_type = CollectionType::from_repr(cl_type)?;
if version != 3 { if version != 3 {
bail!("invalid collection definition"); bail!("invalid collection definition");
} }
let tabs = tab_coll(c_data(b, tab_ofs..)?, tab_num, clr_num)?; let tabs = color_tables(b, tab_ofs, tab_num, clr_num)?;
let bmps = bmp_coll(b, bmp_ofs, bmp_num)?; let bmps = rd_ofstable(b, bmp_ofs, bmp_num, bitmap)?;
let frms = frm_coll(b, frm_ofs, frm_num)?; let frms = rd_ofstable(b, frm_ofs, frm_num, frame)?;
let seqs = seq_coll(b, seq_ofs, seq_num)?; let seqs = rd_ofstable(b, seq_ofs, seq_num, sequence)?;
Ok(Collection{ctyp: cl_type, tabs, bmps, frms, seqs}) Ok(Collection{ctyp: cl_type, tabs, bmps, frms, seqs})
} }
@ -217,19 +217,30 @@ pub fn read_shapes(b: &[u8]) -> ResultS<Vec<CollectionDef>>
let mut p = 0; let mut p = 0;
for _ in 0..32 { for _ in 0..32 {
let lo_ofs = c_u32b(b, p + 4)? as usize; read_data! {
let lo_len = c_u32b(b, p + 8)? as usize; p + 32, BE in b =>
let hi_ofs = c_u32b(b, p + 12)? as usize; lo_ofs = u32[p + 4] as usize;
let hi_len = c_u32b(b, p + 16)? as usize; lo_len = u32[p + 8] as usize;
hi_ofs = u32[p + 12] as usize;
hi_len = u32[p + 16] as usize;
}
let c_lo = if lo_ofs != u32::max_value() as usize { let c_lo = if lo_ofs != u32::max_value() as usize {
Some(collection(c_data(b, lo_ofs..lo_ofs + lo_len)?)?) if b.len() < lo_ofs + lo_len {
bail!("not enough data");
} else {
Some(collection(&b[lo_ofs..lo_ofs + lo_len])?)
}
} else { } else {
None None
}; };
let c_hi = if hi_ofs != u32::max_value() as usize { let c_hi = if hi_ofs != u32::max_value() as usize {
Some(collection(c_data(b, hi_ofs..hi_ofs + hi_len)?)?) if b.len() < hi_ofs + hi_len {
bail!("not enough data");
} else {
Some(collection(&b[hi_ofs..hi_ofs + hi_len])?)
}
} else { } else {
None None
}; };

View File

@ -7,26 +7,34 @@ use std::collections::HashMap;
fn sound(b: &[u8]) -> ResultS<Sound16> fn sound(b: &[u8]) -> ResultS<Sound16>
{ {
let len = c_u32b(b, 4)? as usize; read_data! {
let rate = c_u16b(b, 8)?; 21, BE in b =>
let lp_beg = c_u32b(b, 12)? as usize; len = u32[4] as usize;
let lp_end = c_u32b(b, 16)? as usize; rate = u16[8];
let magic = c_byte(b, 20)?; lp_beg = u32[12] as usize;
lp_end = u32[16] as usize;
magic = u8[20];
}
match magic { match magic {
0 => { 0 => {
let stream = c_data(b, 22..22 + len)?; let stream = &b[22..22 + len];
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream)) Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
} }
0xFF => { 0xFF => {
let len = c_u32b(b, 22)? as usize; read_data! {
match c_u16b(b, 48)? { 63, BE in b =>
len = u32[22] as usize;
bps = u16[48];
}
match bps {
16 => { 16 => {
let stream = c_data(b, 63..63 + len * 2)?; let stream = &b[63..63 + len * 2];
Ok(Sound16::new_from_16(rate, lp_beg, lp_end, stream)) Ok(Sound16::new_from_16(rate, lp_beg, lp_end, stream))
} }
8 => { 8 => {
let stream = c_data(b, 63..63 + len)?; let stream = &b[63..63 + len];
Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream)) Ok(Sound16::new_from_8(rate, lp_beg, lp_end, stream))
} }
_ => bail!("bad bits per sample"), _ => bail!("bad bits per sample"),
@ -38,16 +46,20 @@ fn sound(b: &[u8]) -> ResultS<Sound16>
fn sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>> fn sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
{ {
let index = c_u16b(b, 0)?; read_data! {
let volume = c_u16b(b, 2)?; 64, BE in b =>
let flags = c_u16b(b, 4)?; index = u16[0];
let chance = c_u16b(b, 6)?; volume = u16[2];
let pitch_lo = c_u32b(b, 8)?; flags = u16[4];
let pitch_hi = c_u32b(b, 12)?; chance = u16[6];
let n_sounds = c_u16b(b, 16)? as usize; pitch_lo = u32[8];
let grp_ofs = c_u32b(b, 20)? as usize; pitch_hi = u32[12];
let volume = Volume::from_repr(volume)?; n_sounds = u16[16] as usize;
grp_ofs = u32[20] as usize;
}
let flags = ok!(SoundFlags::from_bits(flags), "bad SoundFlags")?; let flags = ok!(SoundFlags::from_bits(flags), "bad SoundFlags")?;
let volume = Volume::from_repr(volume)?;
let pitch_lo = Fixed::from_bits(pitch_lo); let pitch_lo = Fixed::from_bits(pitch_lo);
let pitch_hi = Fixed::from_bits(pitch_hi); let pitch_hi = Fixed::from_bits(pitch_hi);
@ -63,7 +75,7 @@ fn sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
let mut p = 36; let mut p = 36;
for _ in 0..n_sounds { for _ in 0..n_sounds {
ofs.push(grp_ofs + c_u32b(b, p)? as usize); ofs.push(grp_ofs + u32b(&b[p..]) as usize);
p += 4; p += 4;
} }
@ -75,10 +87,13 @@ fn sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>> pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
{ {
let version = c_u32b(b, 0)?; read_data! {
let magic = c_iden(b, 4)?; 260, BE in b =>
let src_num = c_u16b(b, 8)? as usize; // TODO version = u32[0];
let snd_num = c_u16b(b, 10)? as usize; magic = iden[4];
src_num = u16[8] as usize;
snd_num = u16[10] as usize;
}
if version != 1 || magic != *b"snd2" { if version != 1 || magic != *b"snd2" {
bail!("bad sound header"); bail!("bad sound header");
@ -91,9 +106,9 @@ pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
let mut st = HashMap::with_capacity(snd_num); let mut st = HashMap::with_capacity(snd_num);
for _ in 0..snd_num { for _ in 0..snd_num {
if let Some((ofs, idx, mut def)) = sound_def(c_data(b, p..p + 64)?)? { if let Some((ofs, idx, mut def)) = sound_def(&b[p..p + 64])? {
for &ofs in &ofs { for &ofs in &ofs {
def.sounds.push(sound(c_data(b, ofs..)?)?); def.sounds.push(sound(&b[ofs..])?);
} }
st.insert(idx, def); st.insert(idx, def);

View File

@ -1,18 +1,21 @@
use crate::durandal::{bin::*, err::*, text::*}; use crate::durandal::{err::*, text::*};
use bitflags::bitflags; use bitflags::bitflags;
use serde::Serialize; use serde::Serialize;
use std::fmt; use std::fmt;
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group> fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
{ {
let flags = c_u16b(b, 0)?; read_data! {
let ttype = c_u16b(b, 2)?; 12, BE in b =>
let pdata = c_i16b(b, 4)?; flags = u16[0];
let start = c_u16b(b, 6)? as usize; ttype = u16[2];
let size = c_u16b(b, 8)? as usize; pdata = i16[4];
let lines = c_u16b(b, 10)?; start = u16[6] as usize;
let text = c_data(text, start..start + size)?; size = u16[8] as usize;
let text = mac_roman_conv(text); lines = u16[10];
}
let text = mac_roman_conv(&text[start..start + size]);
let flags = ok!(GroupFlags::from_bits(flags), "bad GroupFlags")?; let flags = ok!(GroupFlags::from_bits(flags), "bad GroupFlags")?;
let ttype = GroupType::from_repr(ttype)?; let ttype = GroupType::from_repr(ttype)?;
@ -21,9 +24,12 @@ fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
fn read_face(b: &[u8]) -> ResultS<Face> fn read_face(b: &[u8]) -> ResultS<Face>
{ {
let start = c_u16b(b, 0)? as usize; read_data! {
let face = c_u16b(b, 2)?; 6, BE in b =>
let color = c_u16b(b, 4)?; start = u16[0] as usize;
face = u16[2];
color = u16[4];
}
Ok(Face{start, face, color}) Ok(Face{start, face, color})
} }
@ -33,11 +39,16 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
const SIZE_GROUP: usize = 12; const SIZE_GROUP: usize = 12;
const SIZE_FACE: usize = 6; const SIZE_FACE: usize = 6;
let end = c_u16b(b, 0)? as usize; read_data! {
let encoded = c_u16b(b, 2)? & 1 != 0; 10, BE in b =>
let lines = c_u16b(b, 4)?; end = u16[0] as usize;
let group_n = c_u16b(b, 6)? as usize; encoded = u16[2];
let face_n = c_u16b(b, 8)? as usize; lines = u16[4];
group_n = u16[6] as usize;
face_n = u16[8] as usize;
}
let encoded = encoded != 0;
let mut groups = Vec::with_capacity(group_n); let mut groups = Vec::with_capacity(group_n);
let mut faces = Vec::with_capacity(face_n); let mut faces = Vec::with_capacity(face_n);
@ -45,7 +56,7 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
let mut p = 10; let mut p = 10;
let text_st = p + SIZE_GROUP * group_n + SIZE_FACE * face_n; let text_st = p + SIZE_GROUP * group_n + SIZE_FACE * face_n;
let text = c_data(b, text_st..end)?; let text = &b[text_st..end];
let text = if encoded { let text = if encoded {
fuck_string(text) fuck_string(text)
} else { } else {
@ -53,12 +64,12 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
}; };
for _ in 0..group_n { for _ in 0..group_n {
groups.push(read_group(c_data(b, p..)?, &text)?); groups.push(read_group(&b[p..], &text)?);
p += SIZE_GROUP; p += SIZE_GROUP;
} }
for _ in 0..face_n { for _ in 0..face_n {
faces.push(read_face(c_data(b, p..)?)?); faces.push(read_face(&b[p..])?);
p += SIZE_FACE; p += SIZE_FACE;
} }

View File

@ -8,14 +8,18 @@ impl Wad<'_>
{ {
pub fn new(b: &[u8]) -> ResultS<Wad> pub fn new(b: &[u8]) -> ResultS<Wad>
{ {
let wadver = c_u16b(b, 0)?; read_data! {
let dataver = c_u16b(b, 2)?; 128, BE in b =>
let origname = c_data(b, 4..68)?; wadver = u16[0];
let dirofs = c_u32b(b, 72)? as usize; dataver = u16[2];
let numents = c_u16b(b, 76)? as usize; origname = u8[4..68] array;
let appsize = c_u16b(b, 78)? as usize; dirofs = u32[72] as usize;
let wcnksize = c_u16b(b, 80)? as usize; numents = u16[76] as usize;
let wentsize = c_u16b(b, 82)? as usize; appsize = u16[78] as usize;
wcnksize = u16[80] as usize;
wentsize = u16[82] as usize;
}
let wadver = Ver::from_repr(wadver)?; let wadver = Ver::from_repr(wadver)?;
let origname = mac_roman_conv(origname); let origname = mac_roman_conv(origname);
@ -38,17 +42,22 @@ impl Wad<'_>
let mut p = dirofs; let mut p = dirofs;
for i in 0..numents { for i in 0..numents {
let offset = c_u32b(b, p)? as usize; read_data! {
let size = c_u32b(b, p + 4)? as usize; p + entsize, BE in b =>
let index = if !is_old {c_u16b(b, p + 8)?} else {i as u16}; offset = u32[p] as usize;
size = u32[p + 4] as usize;
index = u16[p + 8];
}
let index = if !is_old {index} else {i as u16};
if offset + size > b.len() { if offset + size > b.len() {
bail!("not enough data for entry"); bail!("not enough data for entry");
} }
let cnkdata = c_data(b, offset..offset + size)?; let cnkdata = &b[offset..offset + size];
let chunks = get_chunks(cnkdata, cnksize)?; let chunks = get_chunks(cnkdata, cnksize)?;
let appdata = c_data(b, p..p + appsize)?; let appdata = &b[p..p + appsize];
entries.insert(index, Entry{chunks, appdata}); entries.insert(index, Entry{chunks, appdata});
@ -65,11 +74,17 @@ fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
let mut p = 0; let mut p = 0;
while p < b.len() { while p < b.len() {
let iden = c_iden(b, p)?; read_data! {
let size = c_u32b(b, p + 8)? as usize; p + cnksize, BE in b =>
iden = iden[p];
size = u32[p + 8] as usize;
}
let beg = p + cnksize; let beg = p + cnksize;
let end = beg + size; let end = beg + size;
chunks.insert(iden, c_data(b, beg..end)?);
chunks.insert(iden, &b[beg..end]);
p = end; p = end;
} }