read_data
parent
b08c370530
commit
baeea71fe4
|
@ -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`.
|
||||
|
|
|
@ -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;
|
||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue