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 serde::Serialize;
use std::{fmt, num::NonZeroU16, slice::SliceIndex};
use std::{fmt, num::NonZeroU16};
/// Returns a `[u8]` from `b` at `i`.
pub fn c_data<I>(b: &[u8], i: I) -> ResultS<&<I as SliceIndex<[u8]>>::Output>
where I: SliceIndex<[u8]>
{
ok!(b.get(i), "not enough data")
#[doc(hidden)]
macro_rules! rd_1 {
// big endian
(BE $b:ident $nam:ident u16 $n:expr) => {
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`.
pub fn c_byte(b: &[u8], i: usize) -> ResultS<u8>
{
match b.get(i) {
Some(&v) => Ok(v),
None => Err(err_msg("not enough data")),
}
macro_rules! read_data {
(
$sz:expr , $ty:ident in $b:ident =>
$( $nam:ident = $t:ident [ $n:expr ] $( $ex:ident )* ; )*
) => {
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 c_iden(b: &[u8], i: usize) -> ResultS<Ident>
pub fn ident(b: &[u8]) -> 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 c_u32b(b: &[u8], i: usize) -> ResultS<u32>
pub fn u32b(b: &[u8]) -> 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 c_u16b(b: &[u8], i: usize) -> ResultS<u16>
pub fn u16b(b: &[u8]) -> 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 c_i32b(b: &[u8], i: usize) -> ResultS<i32>
pub fn i32b(b: &[u8]) -> 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 c_i16b(b: &[u8], i: usize) -> ResultS<i16>
pub fn i16b(b: &[u8]) -> 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 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>>
pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
where T: Sized,
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)
}
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
{
/// Creates an `ObjID` from a `u16`.

View File

@ -1,11 +1,12 @@
//! Library for various utilities.
#[macro_use]
pub mod err;
#[macro_use]
pub mod cenum;
#[macro_use]
pub mod err;
pub mod bin;
pub mod crc;
pub mod file;
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)?;
}
b"Minf" => make_yaml(opt, &map::read_minf(cnk)?)?,
b"EPNT" => make_yaml(opt, &c_array(cnk, map::read_epnt)?)?,
b"PNTS" => make_yaml(opt, &c_array(cnk, map::read_pnts)?)?,
b"LINS" => make_yaml(opt, &c_array(cnk, map::read_lins)?)?,
b"SIDS" => make_yaml(opt, &c_array(cnk, map::read_sids)?)?,
b"POLY" => make_yaml(opt, &c_array(cnk, map::read_poly)?)?,
b"term" => make_yaml(opt, &c_array(cnk, trm::read_term)?)?,
b"EPNT" => make_yaml(opt, &rd_array(cnk, map::read_epnt)?)?,
b"PNTS" => make_yaml(opt, &rd_array(cnk, map::read_pnts)?)?,
b"LINS" => make_yaml(opt, &rd_array(cnk, map::read_lins)?)?,
b"SIDS" => make_yaml(opt, &rd_array(cnk, map::read_sids)?)?,
b"POLY" => make_yaml(opt, &rd_array(cnk, map::read_poly)?)?,
b"term" => make_yaml(opt, &rd_array(cnk, trm::read_term)?)?,
_ => (),
}
}
@ -183,7 +183,7 @@ fn main() -> ResultS<()>
macro_rules! arg {
($name:expr, $ref:expr, $type:expr, $ap:expr, $desc:expr) => {
$ap.refer(&mut $ref).add_option(&[$name], $type, $desc);
}
};
}
let mut ap = ArgumentParser::new();
@ -250,7 +250,7 @@ fn main() -> ResultS<()>
if !opt.wad_c_temp.is_empty() {
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 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 {
"wad:" => process_wad(&opt, b),

View File

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

View File

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

View File

@ -10,13 +10,17 @@ fn read_pm_header<'a>(b: &'a [u8],
im: &Image8)
-> ResultS<(&'a [u8], Header)>
{
let pt_fl = c_u16b(b, 0)?;
let top = c_u16b(b, 2)? as usize;
let left = c_u16b(b, 4)? as usize;
let bottom = c_u16b(b, 6)? as usize;
let right = c_u16b(b, 8)? as usize;
let pack_t = c_u16b(b, 12)?;
let depth = c_u16b(b, 28)?;
read_data! {
36, BE in b =>
pt_fl = u16[0];
top = u16[2] as usize;
left = u16[4] as usize;
bottom = u16[6] as usize;
right = u16[8] as usize;
pack_t = u16[12];
depth = u16[28];
}
let pack_t = PackType::from_repr(pack_t)?;
if pt_fl & 0x8000 == 0 {
@ -31,7 +35,7 @@ fn read_pm_header<'a>(b: &'a [u8],
// get CLUT if packed
let clut = if pack {
let (clut, sz) = get_clut(c_data(b, p..)?)?;
let (clut, sz) = get_clut(&b[p..])?;
p += sz;
Some(clut)
} else {
@ -41,7 +45,7 @@ fn read_pm_header<'a>(b: &'a [u8],
p += 18; // srcRect, dstRect, mode
if clip {
p += c_u16b(b, p)? as usize; // maskRgn
p += u16b(&b[p..]) as usize; // maskRgn
}
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
for _ in 0..im.h() {
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());
p += 1;
}
@ -73,13 +77,13 @@ fn read_pm_ind(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
} else if hdr.rle {
// RLE compressed 1, 2, 4 or 8 bit colormap indices
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};
p += pp;
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());
}
}
@ -99,7 +103,8 @@ fn read_pm_16(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
// uncompressed R5G5B5
for _ in 0..im.h() {
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;
}
}
@ -108,12 +113,13 @@ fn read_pm_16(mut im: Image8, b: &[u8], hdr: Header) -> ResultS<Image8>
} else if hdr.rle {
// RLE compressed R5G5B5
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;
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 {
p += 1;
}
let r = c_byte(b, p)?;
let g = c_byte(b, p + 1)?;
let b = c_byte(b, p + 2)?;
p += 3;
read_data! {
p + 3, BE in b =>
r = u8[p];
g = u8[p + 1];
b = u8[p + 2];
}
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
let pitch = hdr.pitch - im.w(); // remove padding byte from pitch
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;
for x in 0..im.w() {
let r = c_byte(&d, x + im.w())?;
let g = c_byte(&d, x + im.w() * 2)?;
let b = c_byte(&d, x + im.w() * 3)?;
let r = d[x + im.w()];
let g = d[x + im.w() * 2];
let b = d[x + im.w() * 3];
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.
pub fn load_pict(b: &[u8]) -> ResultS<Image8>
{
let h = c_u16b(b, 6)? as usize;
let w = c_u16b(b, 8)? as usize;
read_data! {
10, BE in b =>
h = u16[6] as usize;
w = u16[8] as usize;
}
let im = Image8::new(w, h);
let mut p = 10; // size of header
while p < b.len() {
let op = c_u16b(b, p)?;
read_data! {
p + 2, BE in b =>
op = u16[p];
}
p += 2;
match op {
0x0098 => {
// PackBitsRect
return read_pm_area(im, c_data(b, p..)?, true, false);
return read_pm_area(im, &b[p..], true, false);
}
0x0099 => {
// PackBitsRgn
return read_pm_area(im, c_data(b, p..)?, true, true);
return read_pm_area(im, &b[p..], true, true);
}
0x009a => {
// DirectBitsRect
return read_pm_area(im, c_data(b, p..)?, false, false);
return read_pm_area(im, &b[p..], false, false);
}
0x009b => {
// DirectBitsRgn
return read_pm_area(im, c_data(b, p..)?, false, true);
return read_pm_area(im, &b[p..], false, true);
}
0x8200 => {
// CompressedQuickTime
return read_quicktime_c(im, c_data(b, p..)?);
return read_quicktime_c(im, &b[p..]);
}
0x00ff => {
// OpEndPic
@ -271,8 +291,8 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
0x0033 | // InvertRect
0x0034 => p += 8, // FillRect
0x002d => p += 10, // LineJustify
0x0001 => p += (c_u16b(b, p )? & !1) as usize, // Clip
0x00a1 => p += (c_u16b(b, p+2)? & !1) as usize + 2, // LongComment
0x0001 => p += (u16b(&b[p.. ]) & !1) as usize, // Clip
0x00a1 => p += (u16b(&b[p+2..]) & !1) as usize + 2, // LongComment
0x100..=
0x7fff => p += (op >> 8) as usize * 2, // Reserved
_ => {
@ -287,23 +307,30 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image8>
/// Read a colorTable structure.
pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color8>, usize)>
{
let dev = c_u16b(b, 4)? & 0x8000 != 0;
let num = c_u16b(b, 6)? as usize + 1;
read_data! {
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 clut = vec![Color8::new(0, 0, 0); num];
for i in 0..num {
// with device mapping, we ignore the index entirely
let n = if !dev {c_u16b(b, p)? as usize} else {i};
let r = c_byte(b, p + 2)?;
let g = c_byte(b, p + 4)?;
let b = c_byte(b, p + 6)?;
if n >= clut.len() {
bail!("bad clut index");
read_data! {
p + 8, BE in b =>
n = u16[p] as usize;
r = u8[p + 2];
g = u8[p + 4];
b = u8[p + 6];
}
// 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);
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 sz = if pitch > 250 {
(c_u16b(b, 0)? as usize + 2, p += 2).0
(u16b(b) as usize + 2, p += 2).0
} else {
(c_byte(b, 0)? as usize + 1, p += 1).0
(b[0] as usize + 1, p += 1).0
};
while p < sz {
let szf = c_byte(b, p)?;
let szf = b[p];
let cmp = szf & 0x80 != 0;
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 serde::Serialize;
fn color(b: &[u8]) -> ResultS<(usize, ColorShp)>
fn color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
{
let l = c_byte(b, 0)?;
let i = c_byte(b, 1)? as usize;
let r = c_u16b(b, 2)?;
let g = c_u16b(b, 4)?;
let b = c_u16b(b, 6)?;
read_data! {
8, BE in b =>
l = u8[0];
i = u8[1];
r = u16[2];
g = u16[4];
b = u16[6];
}
let l = match l {
128 => Ok(true),
0 => Ok(false),
_ => 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],
tab_num: usize,
clr_num: usize)
-> ResultS<Vec<Vec<ColorShp>>>
fn color_tables(b: &[u8],
tab_ofs: usize,
tab_num: usize,
clr_num: usize)
-> ResultS<Vec<Vec<ColorShp>>>
{
let mut tabs = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
let mut p = 0;
let end = tab_num * clr_num * 8;
for clut in tabs.iter_mut().take(tab_num) {
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;
for clut in v.iter_mut().take(tab_num) {
for _ in 0..clr_num {
let (i, cr) = color(c_data(b, p..)?)?;
*ok!(clut.get_mut(i), "invalid index")? = cr;
color(&b[p..p + 8], clut)?;
p += 8;
}
}
Ok(tabs)
Ok(v)
}
fn bitmap(b: &[u8]) -> ResultS<Bitmap>
{
let width = c_u16b(b, 0)? as usize;
let height = c_u16b(b, 2)? as usize;
let compr = c_u16b(b, 4)? == u16::max_value();
let flags = c_u16b(b, 6)?;
let depth = c_u16b(b, 8)?;
read_data! {
26, BE in b =>
width = u16[0] as usize;
height = u16[2] as usize;
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 alpha = flags.contains(BmpFlags::Transparent);
let cmajr = flags.contains(BmpFlags::ColumnMajor);
@ -65,21 +88,24 @@ fn bitmap(b: &[u8]) -> ResultS<Bitmap>
if compr {
// compressed scanlines (transparency RLE)
for _ in 0..scanlines {
let fst = c_u16b(b, p)? as usize;
let lst = c_u16b(b, p + 2)? as usize;
if lst < fst || fst > pitch || lst > pitch {
bail!("invalid compressed scanline");
read_data! {
p + 4, BE in b =>
fst = u16[p] as usize;
lst = u16[p + 2] as usize;
}
let end = lst - fst;
p += 4;
if lst < fst || fst > pitch || lst > pitch || p + end >= b.len() {
bail!("invalid compressed scanline");
}
for _ in 0..fst {
bmp.cr.push(0);
}
let end = lst - fst;
bmp.cr.extend_from_slice(c_data(b, p..p + end)?);
bmp.cr.extend_from_slice(&b[p..p + end]);
for _ in lst..pitch {
bmp.cr.push(0);
@ -89,37 +115,31 @@ fn bitmap(b: &[u8]) -> ResultS<Bitmap>
}
} else {
// 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)
}
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>
{
let flags = c_u16b(b, 0)?;
let min_lt = c_u32b(b, 2)?;
let bmp_ind = c_u16b(b, 6)? as usize;
let wrl_l = c_u16b(b, 16)?;
let wrl_r = c_u16b(b, 18)?;
let wrl_t = c_u16b(b, 20)?;
let wrl_b = c_u16b(b, 22)?;
let wrl_x = c_u16b(b, 24)?;
let wrl_y = c_u16b(b, 26)?;
read_data! {
36, BE in b =>
flags = u16[0];
min_lt = u32[2];
bmp_ind = u16[6] as usize;
wrl_l = u16[16];
wrl_r = u16[18];
wrl_t = u16[20];
wrl_b = u16[22];
wrl_x = u16[24];
wrl_y = u16[26];
}
let flags = ok!(FrameFlags::from_bits(flags), "bad flag")?;
let min_lt = Fixed::from_bits(min_lt);
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})
}
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>
{
let name = c_data(b, 4..38)?;
let v_type = c_u16b(b, 38)?;
let frames = c_u16b(b, 40)?;
let ticks = c_u16b(b, 42)?;
let key = c_u16b(b, 44)?;
let xfer = c_u16b(b, 46)?;
let xfer_pd = c_u16b(b, 48)?;
let snd_beg = c_u16b(b, 50)?;
let snd_key = c_u16b(b, 52)?;
let snd_end = c_u16b(b, 54)?;
let loop_f = c_u16b(b, 58)?;
read_data! {
88, BE in b =>
name = u8[4..38] array;
v_type = u16[38];
frames = u16[40];
ticks = u16[42];
key = u16[44];
xfer = u16[46];
xfer_pd = u16[48];
snd_beg = u16[50];
snd_key = u16[52];
snd_end = u16[54];
loop_f = u16[58];
}
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 v_type = ViewType::from_repr(v_type)?;
let snd_beg = ObjID::from_repr(snd_beg);
let snd_key = ObjID::from_repr(snd_key);
let snd_end = ObjID::from_repr(snd_end);
@ -170,43 +180,33 @@ fn sequence(b: &[u8]) -> ResultS<Sequence>
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>
{
let version = c_u16b(b, 0)?;
let cl_type = c_u16b(b, 2)?;
let clr_num = c_u16b(b, 6)? as usize;
let tab_num = c_u16b(b, 8)? as usize;
let tab_ofs = c_u32b(b, 10)? as usize;
let seq_num = c_u16b(b, 14)? as usize;
let seq_ofs = c_u32b(b, 16)? as usize;
let frm_num = c_u16b(b, 20)? as usize;
let frm_ofs = c_u32b(b, 22)? as usize;
let bmp_num = c_u16b(b, 26)? as usize;
let bmp_ofs = c_u32b(b, 28)? as usize;
read_data! {
544, BE in b =>
version = u16[0];
cl_type = u16[2];
clr_num = u16[6] as usize;
tab_num = u16[8] as usize;
tab_ofs = u32[10] as usize;
seq_num = u16[14] as usize;
seq_ofs = u32[16] as usize;
frm_num = u16[20] 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)?;
if version != 3 {
bail!("invalid collection definition");
}
let tabs = tab_coll(c_data(b, tab_ofs..)?, tab_num, clr_num)?;
let bmps = bmp_coll(b, bmp_ofs, bmp_num)?;
let frms = frm_coll(b, frm_ofs, frm_num)?;
let seqs = seq_coll(b, seq_ofs, seq_num)?;
let tabs = color_tables(b, tab_ofs, tab_num, clr_num)?;
let bmps = rd_ofstable(b, bmp_ofs, bmp_num, bitmap)?;
let frms = rd_ofstable(b, frm_ofs, frm_num, frame)?;
let seqs = rd_ofstable(b, seq_ofs, seq_num, sequence)?;
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;
for _ in 0..32 {
let lo_ofs = c_u32b(b, p + 4)? as usize;
let lo_len = c_u32b(b, p + 8)? as usize;
let hi_ofs = c_u32b(b, p + 12)? as usize;
let hi_len = c_u32b(b, p + 16)? as usize;
read_data! {
p + 32, BE in b =>
lo_ofs = u32[p + 4] 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 {
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 {
None
};
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 {
None
};

View File

@ -7,26 +7,34 @@ use std::collections::HashMap;
fn sound(b: &[u8]) -> ResultS<Sound16>
{
let len = c_u32b(b, 4)? as usize;
let rate = c_u16b(b, 8)?;
let lp_beg = c_u32b(b, 12)? as usize;
let lp_end = c_u32b(b, 16)? as usize;
let magic = c_byte(b, 20)?;
read_data! {
21, BE in b =>
len = u32[4] as usize;
rate = u16[8];
lp_beg = u32[12] as usize;
lp_end = u32[16] as usize;
magic = u8[20];
}
match magic {
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))
}
0xFF => {
let len = c_u32b(b, 22)? as usize;
match c_u16b(b, 48)? {
read_data! {
63, BE in b =>
len = u32[22] as usize;
bps = u16[48];
}
match bps {
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))
}
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))
}
_ => 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)>>
{
let index = c_u16b(b, 0)?;
let volume = c_u16b(b, 2)?;
let flags = c_u16b(b, 4)?;
let chance = c_u16b(b, 6)?;
let pitch_lo = c_u32b(b, 8)?;
let pitch_hi = c_u32b(b, 12)?;
let n_sounds = c_u16b(b, 16)? as usize;
let grp_ofs = c_u32b(b, 20)? as usize;
let volume = Volume::from_repr(volume)?;
read_data! {
64, BE in b =>
index = u16[0];
volume = u16[2];
flags = u16[4];
chance = u16[6];
pitch_lo = u32[8];
pitch_hi = u32[12];
n_sounds = u16[16] as usize;
grp_ofs = u32[20] as usize;
}
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_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;
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;
}
@ -75,10 +87,13 @@ fn sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
{
let version = c_u32b(b, 0)?;
let magic = c_iden(b, 4)?;
let src_num = c_u16b(b, 8)? as usize; // TODO
let snd_num = c_u16b(b, 10)? as usize;
read_data! {
260, BE in b =>
version = u32[0];
magic = iden[4];
src_num = u16[8] as usize;
snd_num = u16[10] as usize;
}
if version != 1 || magic != *b"snd2" {
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);
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 {
def.sounds.push(sound(c_data(b, ofs..)?)?);
def.sounds.push(sound(&b[ofs..])?);
}
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 serde::Serialize;
use std::fmt;
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
{
let flags = c_u16b(b, 0)?;
let ttype = c_u16b(b, 2)?;
let pdata = c_i16b(b, 4)?;
let start = c_u16b(b, 6)? as usize;
let size = c_u16b(b, 8)? as usize;
let lines = c_u16b(b, 10)?;
let text = c_data(text, start..start + size)?;
let text = mac_roman_conv(text);
read_data! {
12, BE in b =>
flags = u16[0];
ttype = u16[2];
pdata = i16[4];
start = u16[6] as usize;
size = u16[8] as usize;
lines = u16[10];
}
let text = mac_roman_conv(&text[start..start + size]);
let flags = ok!(GroupFlags::from_bits(flags), "bad GroupFlags")?;
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>
{
let start = c_u16b(b, 0)? as usize;
let face = c_u16b(b, 2)?;
let color = c_u16b(b, 4)?;
read_data! {
6, BE in b =>
start = u16[0] as usize;
face = u16[2];
color = u16[4];
}
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_FACE: usize = 6;
let end = c_u16b(b, 0)? as usize;
let encoded = c_u16b(b, 2)? & 1 != 0;
let lines = c_u16b(b, 4)?;
let group_n = c_u16b(b, 6)? as usize;
let face_n = c_u16b(b, 8)? as usize;
read_data! {
10, BE in b =>
end = u16[0] as usize;
encoded = u16[2];
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 faces = Vec::with_capacity(face_n);
@ -45,7 +56,7 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
let mut p = 10;
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 {
fuck_string(text)
} else {
@ -53,12 +64,12 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
};
for _ in 0..group_n {
groups.push(read_group(c_data(b, p..)?, &text)?);
groups.push(read_group(&b[p..], &text)?);
p += SIZE_GROUP;
}
for _ in 0..face_n {
faces.push(read_face(c_data(b, p..)?)?);
faces.push(read_face(&b[p..])?);
p += SIZE_FACE;
}

View File

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