partially format code with rustfmt

png-branch
an 2019-02-09 00:53:27 -05:00
parent dd5bf03252
commit 6d99752e6e
16 changed files with 701 additions and 456 deletions

View File

@ -2,6 +2,7 @@ binop_separator = "Back"
brace_style = "AlwaysNextLine"
condense_wildcard_suffixes = true
enum_discrim_align_threshold = 40
fn_single_line = true
format_doc_comments = true
format_macro_matchers = true
format_strings = true

View File

@ -12,23 +12,63 @@ pub trait BinUtil
fn c_u16b(&self, i: usize) -> ResultS<u16>;
fn c_i32b(&self, i: usize) -> ResultS<i32>
{match self.c_u32b(i) {Ok(n) => Ok(n as i32), Err(e) => Err(e)}}
{
match self.c_u32b(i) {
Ok(n) => Ok(n as i32),
Err(e) => Err(e),
}
}
fn c_i16b(&self, i: usize) -> ResultS<i16>
{match self.c_u16b(i) {Ok(n) => Ok(n as i16), Err(e) => Err(e)}}
{
match self.c_u16b(i) {
Ok(n) => Ok(n as i16),
Err(e) => Err(e),
}
}
// Optional
fn o_iden(&self, i: usize) -> Option<Ident> {self.c_iden(i).ok()}
fn o_u32b(&self, i: usize) -> Option<u32> {self.c_u32b(i).ok()}
fn o_u16b(&self, i: usize) -> Option<u16> {self.c_u16b(i).ok()}
fn o_i32b(&self, i: usize) -> Option<i32> {self.c_i32b(i).ok()}
fn o_i16b(&self, i: usize) -> Option<i16> {self.c_i16b(i).ok()}
fn o_iden(&self, i: usize) -> Option<Ident>
{
self.c_iden(i).ok()
}
fn o_u32b(&self, i: usize) -> Option<u32>
{
self.c_u32b(i).ok()
}
fn o_u16b(&self, i: usize) -> Option<u16>
{
self.c_u16b(i).ok()
}
fn o_i32b(&self, i: usize) -> Option<i32>
{
self.c_i32b(i).ok()
}
fn o_i16b(&self, i: usize) -> Option<i16>
{
self.c_i16b(i).ok()
}
// Unchecked
fn b_iden(&self, i: usize) -> Ident {self.c_iden(i).unwrap()}
fn b_u32b(&self, i: usize) -> u32 {self.c_u32b(i).unwrap()}
fn b_u16b(&self, i: usize) -> u16 {self.c_u16b(i).unwrap()}
fn b_i32b(&self, i: usize) -> i32 {self.c_i32b(i).unwrap()}
fn b_i16b(&self, i: usize) -> i16 {self.c_i16b(i).unwrap()}
fn b_iden(&self, i: usize) -> Ident
{
self.c_iden(i).unwrap()
}
fn b_u32b(&self, i: usize) -> u32
{
self.c_u32b(i).unwrap()
}
fn b_u16b(&self, i: usize) -> u16
{
self.c_u16b(i).unwrap()
}
fn b_i32b(&self, i: usize) -> i32
{
self.c_i32b(i).unwrap()
}
fn b_i16b(&self, i: usize) -> i16
{
self.c_i16b(i).unwrap()
}
}
impl BinUtil for [u8]
@ -45,7 +85,10 @@ impl BinUtil for [u8]
fn c_u32b(&self, i: usize) -> ResultS<u32>
{
if i + 3 < self.len() {
Ok(u32::from_be_bytes([self[i], self[i + 1], self[i + 2], self[i + 3]]))
Ok(u32::from_be_bytes([self[i],
self[i + 1],
self[i + 2],
self[i + 3]]))
} else {
Err(err_msg("not enough data"))
}
@ -61,9 +104,21 @@ impl BinUtil for [u8]
}
}
pub fn d_u32b(n: u32) -> [u8; 4] {n.to_be_bytes()}
pub fn d_u16b(n: u16) -> [u8; 2] {n.to_be_bytes()}
pub fn d_i32b(n: i32) -> [u8; 4] {d_u32b(n as u32)}
pub fn d_i16b(n: i16) -> [u8; 2] {d_u16b(n as u16)}
pub fn d_u32b(n: u32) -> [u8; 4]
{
n.to_be_bytes()
}
pub fn d_u16b(n: u16) -> [u8; 2]
{
n.to_be_bytes()
}
pub fn d_i32b(n: i32) -> [u8; 4]
{
d_u32b(n as u32)
}
pub fn d_i16b(n: i16) -> [u8; 2]
{
d_u16b(n as u16)
}
// EOF

View File

@ -2,21 +2,27 @@
fn crc_accum(a: u32) -> u32
{
if a & 1 == 1 {0xedb88320 ^ a >> 1}
else {a >> 1}
if a & 1 == 1 {
0xedb88320 ^ a >> 1
} else {
a >> 1
}
}
fn crc_init() -> [u32; 256]
{
let mut t = [0; 256];
for n in 0..256 {t[n] = (0..8).fold(n as u32, |a, _| crc_accum(a));}
for n in 0..256 {
t[n] = (0..8).fold(n as u32, |a, _| crc_accum(a));
}
t
}
pub fn crc32(b: &[u8], s: u32) -> u32
{
let t = crc_init();
!b.iter().fold(s, |a, &o| {a >> 8 ^ t[(a & 0xff ^ o as u32) as usize]})
!b.iter()
.fold(s, |a, &o| a >> 8 ^ t[(a & 0xff ^ o as u32) as usize])
}
#[test]

View File

@ -1,6 +1,6 @@
//! Error handling.
pub use failure::{Error, Fail, err_msg};
pub use failure::{err_msg, Error, Fail};
use crate::durandal::traits::PrimInt;
use std::fmt;
@ -13,13 +13,17 @@ impl<T> Fail for ReprError<T> where T: PrimInt {}
impl<T> fmt::Display for ReprError<T> where T: PrimInt
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{write!(f, "representation error (got {})", self.0)}
{
write!(f, "representation error (got {})", self.0)
}
}
impl<T> fmt::Debug for ReprError<T> where T: PrimInt
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{fmt::Display::fmt(self, f)}
{
fmt::Display::fmt(self, f)
}
}
pub type ResultS<T> = Result<T, Error>;

View File

@ -1,4 +1,5 @@
use std::{fmt, fmt::Write, ops};
use std::{fmt::{self, Write},
ops};
pub struct Fx32(i32);
@ -8,55 +9,108 @@ impl Fx32
const FRACMASK: u32 = 0xFFFF;
const ONE: i32 = 1 << Fx32::FRACBITS;
pub fn to_bits(&self) -> u32 {self.0 as u32}
pub fn set_bits(&mut self, bits: u32) {self.0 = bits as i32}
pub fn from_bits(bits: u32) -> Fx32 {Fx32( bits as i32)}
pub fn to_bits(&self) -> u32
{
self.0 as u32
}
pub fn integ(&self) -> i16 {(self.0 >> Fx32::FRACBITS) as i16}
pub fn fract(&self) -> u16 {(self.0 as u32 & Fx32::FRACMASK) as u16}
pub fn set_bits(&mut self, bits: u32)
{
self.0 = bits as i32
}
pub fn mul_i(&self, n: i32) -> Fx32 {Fx32(self.0 * n)}
pub fn div_i(&self, n: i32) -> Fx32 {Fx32(self.0 / n)}
pub fn from_bits(bits: u32) -> Fx32
{
Fx32(bits as i32)
}
pub fn integ(&self) -> i16
{
(self.0 >> Fx32::FRACBITS) as i16
}
pub fn fract(&self) -> u16
{
(self.0 as u32 & Fx32::FRACMASK) as u16
}
pub fn mul_i(&self, n: i32) -> Fx32
{
Fx32(self.0 * n)
}
pub fn div_i(&self, n: i32) -> Fx32
{
Fx32(self.0 / n)
}
}
impl From<i32> for Fx32 {fn from(n: i32) -> Fx32 {Fx32(n << Fx32::FRACBITS)}}
impl From<i32> for Fx32
{
fn from(n: i32) -> Fx32
{
Fx32(n << Fx32::FRACBITS)
}
}
impl ops::Add for Fx32
{
type Output = Fx32;
fn add(self, o: Fx32) -> Fx32 {Fx32(self.0 + o.0)}
fn add(self, o: Fx32) -> Fx32
{
Fx32(self.0 + o.0)
}
}
impl ops::Sub for Fx32
{
type Output = Fx32;
fn sub(self, o: Fx32) -> Fx32 {Fx32(self.0 - o.0)}
fn sub(self, o: Fx32) -> Fx32
{
Fx32(self.0 - o.0)
}
}
impl ops::Mul for Fx32
{
type Output = Fx32;
fn mul(self, o: Fx32) -> Fx32
{Fx32((self.0 as i64 * o.0 as i64 / Fx32::ONE as i64) as i32)}
{
Fx32((self.0 as i64 * o.0 as i64 / Fx32::ONE as i64) as i32)
}
}
impl ops::Div for Fx32
{
type Output = Fx32;
fn div(self, o: Fx32) -> Fx32
{Fx32((self.0 as i64 * Fx32::ONE as i64 / o.0 as i64) as i32)}
{
Fx32((self.0 as i64 * Fx32::ONE as i64 / o.0 as i64) as i32)
}
}
impl ops::Neg for Fx32
{
type Output = Fx32;
fn neg(self) -> Fx32 {Fx32(-self.0)}
fn neg(self) -> Fx32
{
Fx32(-self.0)
}
}
impl ops::Not for Fx32
{
type Output = Fx32;
fn not(self) -> Fx32 {Fx32(!self.0)}
fn not(self) -> Fx32
{
Fx32(!self.0)
}
}
impl fmt::Display for Fx32
@ -83,7 +137,9 @@ impl fmt::Display for Fx32
impl fmt::Debug for Fx32
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{fmt::Display::fmt(self, f)}
{
fmt::Display::fmt(self, f)
}
}
#[test]
@ -93,9 +149,9 @@ fn fx32_basic_ops()
assert_eq!((Fx32::from(1) + 1.into()).to_bits(), 2 << Fx32::FRACBITS);
assert_eq!((Fx32::from(2) - 1.into()).to_bits(), 1 << Fx32::FRACBITS);
assert_eq!((Fx32::from(6) * 2.into()).to_bits(), 12 << Fx32::FRACBITS);
assert_eq!((Fx32::from(6).mul_i(2) ).to_bits(), 12 << Fx32::FRACBITS);
assert_eq!((Fx32::from(6).mul_i(2)).to_bits(), 12 << Fx32::FRACBITS);
assert_eq!((Fx32::from(7) / 2.into()).to_bits(), seven_div_2);
assert_eq!((Fx32::from(7).div_i(2) ).to_bits(), seven_div_2);
assert_eq!((Fx32::from(7).div_i(2)).to_bits(), seven_div_2);
}
#[test]
@ -111,7 +167,8 @@ fn fx32_printing()
{
assert_eq!(format!("{}", Fx32::from(6)), "6.0");
assert_eq!(format!("{}", Fx32::from(7).div_i(2)), "3.5");
assert_eq!(format!("{:7.7}", Fx32::from_bits(0xDEAD_BEEF)), " -8531.7458343");
assert_eq!(format!("{:7.7}", Fx32::from_bits(0xDEAD_BEEF)),
" -8531.7458343");
}
// EOF

View File

@ -39,10 +39,19 @@ impl Image
{
/// Creates a new Image structure.
pub fn new(w: usize, h: usize) -> Image
{Image{w, h, cr: Vec::with_capacity(w * h)}}
{
Image{w, h, cr: Vec::with_capacity(w * h)}
}
pub fn w(&self) -> usize {self.w}
pub fn h(&self) -> usize {self.h}
pub fn w(&self) -> usize
{
self.w
}
pub fn h(&self) -> usize
{
self.h
}
}
impl Index<(usize, usize)> for Image
@ -50,13 +59,17 @@ impl Index<(usize, usize)> for Image
type Output = Color;
fn index(&self, (x, y): (usize, usize)) -> &Color
{&self.cr[x + y * self.w]}
{
&self.cr[x + y * self.w]
}
}
impl IndexMut<(usize, usize)> for Image
{
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Color
{&mut self.cr[x + y * self.w]}
{
&mut self.cr[x + y * self.w]
}
}
// EOF

View File

@ -11,8 +11,11 @@ pub fn dump_mem(b: &[u8])
p = 0;
}
if c.is_ascii_graphic() {eprint!(" {} ", c as char);}
else {eprint!("{:02X} ", c);}
if c.is_ascii_graphic() {
eprint!(" {} ", c as char);
} else {
eprint!("{:02X} ", c);
}
p += 3;
}
@ -26,7 +29,9 @@ pub fn to_binsize(n: u64) -> String
const NAMES: [&str; 4] = ["kB", "MB", "GB", "TB"];
// empty size
if n == 0 {return String::from("empty");}
if n == 0 {
return String::from("empty");
}
// terabytes, gigabytes, megabytes, kilobytes
for i in (1..=4).rev() {
@ -47,8 +52,16 @@ pub fn fuck_string(s: &[u8]) -> Vec<u8>
let l = s.len();
let mut p = 0;
for _ in 0..l / 4 {p += 2; v[p] ^= 0xfe; v[p + 1] ^= 0xed; p += 2;}
for _ in 0..l % 4 {v[p] ^= 0xfe; p += 1;}
for _ in 0..l / 4 {
p += 2;
v[p] ^= 0xfe;
v[p + 1] ^= 0xed;
p += 2;
}
for _ in 0..l % 4 {
v[p] ^= 0xfe;
p += 1;
}
v
}
@ -59,49 +72,43 @@ pub fn mac_roman_conv(s: &[u8]) -> String
let mut v = String::with_capacity(s.len());
for i in 0..s.len() {
if s[i] == 0 {break;}
else if s[i] & 0x80 != 0 {v.push(TR[s[i] as usize & 0x7f]);}
else if s[i] == b'\r' {v.push('\n');}
else {v.push(s[i] as char);}
if s[i] == 0 {
break;
} else if s[i] & 0x80 != 0 {
v.push(TR[s[i] as usize & 0x7f]);
} else if s[i] == b'\r' {
v.push('\n');
} else {
v.push(s[i] as char);
}
}
v
}
const TR: [char; 128] = [
'\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}',
'\u{00d1}', '\u{00d6}', '\u{00dc}', '\u{00e1}',
'\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
'\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}',
'\u{00ea}', '\u{00eb}', '\u{00ed}', '\u{00ec}',
'\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}',
'\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}',
'\u{00fa}', '\u{00f9}', '\u{00fb}', '\u{00fc}',
'\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}',
'\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}',
'\u{00ae}', '\u{00a9}', '\u{2122}', '\u{00b4}',
'\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}',
'\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}',
'\u{00a5}', '\u{00b5}', '\u{2202}', '\u{2211}',
'\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}',
'\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}',
'\u{00bf}', '\u{00a1}', '\u{00ac}', '\u{221a}',
'\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}',
'\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}',
'\u{00c3}', '\u{00d5}', '\u{0152}', '\u{0153}',
'\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}',
'\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}',
'\u{00ff}', '\u{0178}', '\u{2044}', '\u{20ac}',
'\u{2039}', '\u{203a}', '\u{fb01}', '\u{fb02}',
'\u{2021}', '\u{00b7}', '\u{201a}', '\u{201e}',
'\u{2030}', '\u{00c2}', '\u{00ca}', '\u{00c1}',
'\u{00cb}', '\u{00c8}', '\u{00cd}', '\u{00ce}',
'\u{00cf}', '\u{00cc}', '\u{00d3}', '\u{00d4}',
'\u{f8ff}', '\u{00d2}', '\u{00da}', '\u{00db}',
'\u{00d9}', '\u{0131}', '\u{02c6}', '\u{02dc}',
'\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}',
'\u{00b8}', '\u{02dd}', '\u{02db}', '\u{02c7}'
];
const TR: [char; 128] =
['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}',
'\u{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
'\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}', '\u{00ea}', '\u{00eb}',
'\u{00ed}', '\u{00ec}', '\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}',
'\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}', '\u{00fa}', '\u{00f9}',
'\u{00fb}', '\u{00fc}', '\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}',
'\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}', '\u{00ae}', '\u{00a9}',
'\u{2122}', '\u{00b4}', '\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}',
'\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}', '\u{00a5}', '\u{00b5}',
'\u{2202}', '\u{2211}', '\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}',
'\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}', '\u{00bf}', '\u{00a1}',
'\u{00ac}', '\u{221a}', '\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}',
'\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}', '\u{00c3}', '\u{00d5}',
'\u{0152}', '\u{0153}', '\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}',
'\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}', '\u{00ff}', '\u{0178}',
'\u{2044}', '\u{20ac}', '\u{2039}', '\u{203a}', '\u{fb01}', '\u{fb02}',
'\u{2021}', '\u{00b7}', '\u{201a}', '\u{201e}', '\u{2030}', '\u{00c2}',
'\u{00ca}', '\u{00c1}', '\u{00cb}', '\u{00c8}', '\u{00cd}', '\u{00ce}',
'\u{00cf}', '\u{00cc}', '\u{00d3}', '\u{00d4}', '\u{f8ff}', '\u{00d2}',
'\u{00da}', '\u{00db}', '\u{00d9}', '\u{0131}', '\u{02c6}', '\u{02dc}',
'\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}', '\u{00b8}', '\u{02dd}',
'\u{02db}', '\u{02c7}'];
#[test]
fn to_binsize_integrals()

View File

@ -1,7 +1,10 @@
//! Traits for basic types, because Rust doesn't provide them.
/// Any primitive integer type.
pub trait PrimInt: 'static + Send + Sync + std::fmt::Display + PartialEq {}
pub trait PrimInt:
'static + Send + Sync + std::fmt::Display + PartialEq
{
}
impl PrimInt for u8 {}
impl PrimInt for i8 {}

View File

@ -1,6 +1,7 @@
use maraiah::durandal::{bin::*, chunk::*, err::*, image::Image, text::*};
use maraiah::marathon::{machdr, map, pict, term, wad};
use std::{io, io::Write, fs, env};
use maraiah::{durandal::{bin::*, chunk::*, err::*, image::Image, text::*},
marathon::{machdr, map, pict, term, wad}};
use std::{env, fs,
io::{self, Write}};
fn write_ppm(fname: &str, im: &Image) -> io::Result<()>
{
@ -79,11 +80,11 @@ fn process_wad(b: &[u8]) -> ResultS<()>
fn collection(b: &[u8]) -> ResultS<()>
{
let version = b.c_u16b(0 )?;
let dt_type = b.c_u16b(2 )?;
let flags = b.c_u16b(4 )?;
let colors = b.c_u16b(6 )?;
let clu_num = b.c_u16b(8 )?;
let version = b.c_u16b(0)?;
let dt_type = b.c_u16b(2)?;
let flags = b.c_u16b(4)?;
let colors = b.c_u16b(6)?;
let clu_num = b.c_u16b(8)?;
let clu_ofs = b.c_u32b(10)?;
let seq_num = b.c_u16b(14)?;
let seq_ofs = b.c_u32b(16)?;
@ -109,7 +110,9 @@ fn collection(b: &[u8]) -> ResultS<()>
dbg!(size);
eprintln!("[end of collection]");
if version != 3 {return Err(err_msg("invalid collection version number"));}
if version != 3 {
return Err(err_msg("invalid collection version number"));
}
Ok(())
}
@ -118,12 +121,12 @@ fn process_shp(b: &[u8]) -> ResultS<()>
{
for i in 0..32 {
let p = 32 * i;
let status = b.c_u16b(p+0 )?;
let flags = b.c_u16b(p+2 )?;
let offset_lo = b.c_u32b(p+4 )? as usize;
let length_lo = b.c_u32b(p+8 )? as usize;
let offset_hi = b.c_u32b(p+12)? as usize;
let length_hi = b.c_u32b(p+16)? as usize;
let status = b.c_u16b(p + 0)?;
let flags = b.c_u16b(p + 2)?;
let offset_lo = b.c_u32b(p + 4)? as usize;
let length_lo = b.c_u32b(p + 8)? as usize;
let offset_hi = b.c_u32b(p + 12)? as usize;
let length_hi = b.c_u32b(p + 16)? as usize;
dbg!(i);
dbg!(status);
dbg!(flags);
@ -133,11 +136,11 @@ fn process_shp(b: &[u8]) -> ResultS<()>
dbg!(length_hi);
if offset_lo != u32::max_value() as usize {
eprintln!("collection {} has lo-res frames", i);
collection(&b[offset_lo .. offset_lo + length_lo])?;
collection(&b[offset_lo..offset_lo + length_lo])?;
}
if offset_hi != u32::max_value() as usize {
eprintln!("collection {} has hi-res frames", i);
collection(&b[offset_hi .. offset_hi + length_hi])?;
collection(&b[offset_hi..offset_hi + length_hi])?;
}
}
@ -156,13 +159,13 @@ fn main() -> ResultS<()>
};
let fp = fs::File::open(fna)?;
let mm = unsafe{Mmap::map(&fp)?};
let mm = unsafe {Mmap::map(&fp)?};
let b = &mm[machdr::try_mac_header(&mm)..];
match typ {
"wad:" => process_wad(b),
"shp:" => process_shp(b),
_ => Err(err_msg("invalid file type specified on commandline"))
_ => Err(err_msg("invalid file type specified on commandline")),
}?;
}

View File

@ -6,17 +6,21 @@ use crate::durandal::bin::*;
pub fn check_apple_single(b: &[u8]) -> Option<usize>
{
// check magic numbers
if b[0..8] != [0, 5, 22, 0, 0, 2, 0, 0] {return None;}
if b[0..8] != [0, 5, 22, 0, 0, 2, 0, 0] {
return None;
}
// get the resource fork (entity 1)
let num = b.o_u16b(24)? as usize;
for i in 0..num {
let p = 26 + 12 * i;
let ent = b.o_u32b(p )?;
let ofs = b.o_u32b(p+4)? as usize;
let len = b.o_u32b(p+8)? as usize;
let ent = b.o_u32b(p)?;
let ofs = b.o_u32b(p + 4)? as usize;
let len = b.o_u32b(p + 8)? as usize;
if ent == 1 {return if ofs + len > b.len() {None} else {Some(ofs)};}
if ent == 1 {
return if ofs + len > b.len() {None} else {Some(ofs)};
}
}
// no resource fork
@ -27,7 +31,9 @@ pub fn check_apple_single(b: &[u8]) -> Option<usize>
pub fn check_macbin(b: &[u8]) -> Option<usize>
{
// check legacy version, length, zero fill, and macbin2 version
if b[0] != 0 || b[1] > 63 || b[74] != 0 || b[123] > 129 {return None;}
if b[0] != 0 || b[1] > 63 || b[74] != 0 || b[123] > 129 {
return None;
}
let mut crc = 0;
@ -35,21 +41,31 @@ pub fn check_macbin(b: &[u8]) -> Option<usize>
for i in 0..124 {
for j in 8..16 {
let d = b[i] as (u16) << j;
if (d ^ crc) & 0x8000 != 0 {crc = crc << 1 ^ 0x1021;}
else {crc <<= 1;}
if (d ^ crc) & 0x8000 != 0 {
crc = crc << 1 ^ 0x1021;
} else {
crc <<= 1;
}
}
}
// if ok, resource fork follows
if crc == b.o_u16b(124)? {Some(128)} else {None}
if crc == b.o_u16b(124)? {
Some(128)
} else {
None
}
}
/// Reads a MacBin or AppleSingle header if there is one and returns the
/// offset from the start of the header to the resource fork (if one is found.)
pub fn try_mac_header(b: &[u8]) -> usize
{
if let Some(ofs) = check_macbin(b) {ofs}
else {check_apple_single(b).unwrap_or(0)}
if let Some(ofs) = check_macbin(b) {
ofs
} else {
check_apple_single(b).unwrap_or(0)
}
}
// EOF

View File

@ -1,5 +1,5 @@
use bitflags::bitflags;
use crate::durandal::{bin::*, chunk::*, err::*, fx32::*, text::mac_roman_conv};
use bitflags::bitflags;
use std::fmt;
impl Chunked<Point> for Point
@ -68,7 +68,7 @@ impl Chunked<Side> for Side
{
let stype = b.c_u16b(0)?;
let flags = b.c_u16b(2)?;
let tex_pri = read_side_tex(&b[ 4..10])?;
let tex_pri = read_side_tex(&b[4..10])?;
let tex_sec = read_side_tex(&b[10..16])?;
let tex_tra = read_side_tex(&b[16..22])?;
let ex_tleft = Point::read(&b[22..26])?;
@ -93,11 +93,11 @@ impl Chunker<Minf> for Minf
{
fn chunk(b: &[u8]) -> ResultS<Minf>
{
let env_code = b.c_u16b( 0)?;
let physi_id = b.c_u16b( 2)?;
let music_id = b.c_u16b( 4)?;
let msn_flag = b.c_u16b( 6)?;
let env_flag = b.c_u16b( 8)?;
let env_code = b.c_u16b(0)?;
let physi_id = b.c_u16b(2)?;
let music_id = b.c_u16b(4)?;
let msn_flag = b.c_u16b(6)?;
let env_flag = b.c_u16b(8)?;
let levelnam = mac_roman_conv(&b[18..84]);
let ent_flag = b.c_u32b(84)?;
let msn_flag = MsnFlags::from_bits_truncate(msn_flag);
@ -262,7 +262,9 @@ bitflags! {
impl fmt::Debug for Point
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{write!(f, "({}, {})", self.x, self.y)}
{
write!(f, "({}, {})", self.x, self.y)
}
}
// EOF

View File

@ -4,39 +4,46 @@ use crate::durandal::{bin::*, err::*, image::*};
use generic_array::*;
const PACK_DEFAULT: u16 = 0;
const PACK_NONE : u16 = 1;
const PACK_NOPAD : u16 = 2;
const PACK_RLE16 : u16 = 3;
const PACK_RLE32 : u16 = 4;
const PACK_NONE: u16 = 1;
const PACK_NOPAD: u16 = 2;
const PACK_RLE16: u16 = 3;
const PACK_RLE32: u16 = 4;
/// Process a CopyBits operation.
pub fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> ResultS<Image>
pub fn read_bitmap_area(mut im: Image,
b: &[u8],
packed: bool,
clip: bool)
-> ResultS<Image>
{
let mut p = if !packed {4} else {0};
let (w, h) = (im.w(), im.h());
let pitch_fl = b.c_u16b(p )?;
let top = b.c_u16b(p+ 2)? as usize;
let left = b.c_u16b(p+ 4)? as usize;
let bottom = b.c_u16b(p+ 6)? as usize;
let right = b.c_u16b(p+ 8)? as usize;
let pitch_fl = b.c_u16b(p)?;
let top = b.c_u16b(p + 2)? as usize;
let left = b.c_u16b(p + 4)? as usize;
let bottom = b.c_u16b(p + 6)? as usize;
let right = b.c_u16b(p + 8)? as usize;
// version = b.c_u16b(p+10)?;
let pack_typ = b.c_u16b(p+12)?;
let pack_typ = b.c_u16b(p + 12)?;
// pack_siz = b.c_u32b(p+14)?;
// horz_dpi = b.c_u32b(p+18)?;
// vert_dpi = b.c_u32b(p+22)?;
// format = b.c_u16b(p+26)?;
let depth = b.c_u16b(p+28)?;
let depth = b.c_u16b(p + 28)?;
// comp_n = b.c_u16b(p+30)?;
// comp_d = b.c_u16b(p+32)?;
// planeofs = b.c_u32b(p+34)?;
// clut_id = b.c_u32b(p+38)?;
if pitch_fl & 0x8000 == 0
{return Err(err_msg("PICT1 not supported"));}
if right - left != w || bottom - top != h
{return Err(err_msg("image bounds are incorrect"));}
if pitch_fl & 0x8000 == 0 {
return Err(err_msg("PICT1 not supported"));
}
if right - left != w || bottom - top != h {
return Err(err_msg("image bounds are incorrect"));
}
p += 46; // size of header
@ -51,7 +58,9 @@ pub fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Re
p += 18; // srcRect, dstRect, mode
if clip {p += b.c_u16b(p)? as usize;} // maskRgn
if clip {
p += b.c_u16b(p)? as usize; // maskRgn
}
let rle = pack_typ == PACK_DEFAULT ||
(pack_typ == PACK_RLE16 && depth == 16) ||
@ -79,15 +88,17 @@ pub fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Re
p += pp;
for x in 0..w {im.cr.push(clut[d[x] as usize].clone());}
for x in 0..w {
im.cr.push(clut[d[x] as usize].clone());
}
}
Ok(im)
} else {
Err(err_msg("invalid configuration"))
}
},
16 =>
}
16 => {
if pitch < 8 || pack_typ == PACK_NONE {
// uncompressed R5G5B5
for _ in 0..h {
@ -104,20 +115,25 @@ pub fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Re
p += pp;
for x in 0..w {im.cr.push(Color::from_r5g5b5(d.c_u16b(x*2)?));}
for x in 0..w {
im.cr.push(Color::from_r5g5b5(d.c_u16b(x * 2)?));
}
}
Ok(im)
} else {
Err(err_msg("invalid configuration"))
},
32 =>
}
}
32 => {
if pitch < 8 || pack_typ == PACK_NONE || pack_typ == PACK_NOPAD {
// uncompressed RGB8 or XRGB8
for _ in 0..h {
for _ in 0..w {
if pack_typ != PACK_NOPAD {p += 1;}
let (r, g, b) = (b[p], b[p+1], b[p+2]);
if pack_typ != PACK_NOPAD {
p += 1;
}
let (r, g, b) = (b[p], b[p + 1], b[p + 2]);
p += 3;
im.cr.push(Color{r, g, b, a: 255});
}
@ -133,7 +149,7 @@ pub fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Re
p += pp;
for x in 0..w {
let (r, g, b) = (d[x+w*0], d[x+w*1], d[x+w*2]);
let (r, g, b) = (d[x + w * 0], d[x + w * 1], d[x + w * 2]);
im.cr.push(Color{r, g, b, a: 255});
}
}
@ -141,8 +157,9 @@ pub fn read_bitmap_area(mut im: Image, b: &[u8], packed: bool, clip: bool) -> Re
Ok(im)
} else {
Err(err_msg("invalid configuration"))
},
_ => Err(err_msg("invalid bit depth"))
}
}
_ => Err(err_msg("invalid bit depth")),
}
}
@ -168,12 +185,30 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image>
let op = b.c_u16b((p, p += 2).0)?;
match op {
0x0098 => return read_bitmap_area(im, &b[p..], true, false), // PackBitsRect
0x0099 => return read_bitmap_area(im, &b[p..], true, true ), // PackBitsRgn
0x009a => return read_bitmap_area(im, &b[p..], false, false), // DirectBitsRect
0x009b => return read_bitmap_area(im, &b[p..], false, true ), // DirectBitsRgn
0x8200 => return read_quicktime_c(im, &b[p..]), // CompressedQuickTime
0x00ff => break, // OpEndPic
0x0098 => {
// PackBitsRect
return read_bitmap_area(im, &b[p..], true, false);
}
0x0099 => {
// PackBitsRgn
return read_bitmap_area(im, &b[p..], true, true);
}
0x009a => {
// DirectBitsRect
return read_bitmap_area(im, &b[p..], false, false);
}
0x009b => {
// DirectBitsRgn
return read_bitmap_area(im, &b[p..], false, true);
}
0x8200 => {
// CompressedQuickTime
return read_quicktime_c(im, &b[p..]);
}
0x00ff => {
// OpEndPic
break;
}
// help i'm trapped in an awful metafile format from the 80s
0x0000 | // NoOp
0x001c | // HiliteMode
@ -223,7 +258,9 @@ pub fn load_pict(b: &[u8]) -> ResultS<Image>
0x00a1 => p += (b.c_u16b(p+2)? & !1) as usize + 2, // LongComment
0x100..=
0x7fff => p += (op >> 8) as usize * 2, // Reserved
_ => return Err(err_msg("invalid op in PICT"))
_ => {
return Err(err_msg("invalid op in PICT"));
}
}
}
@ -242,12 +279,15 @@ pub fn get_clut(b: &[u8]) -> ResultS<(Vec<Color>, usize)>
for i in 0..num {
// with device mapping, we ignore the index entirely
let n = if !dev {b[p+1] as usize} else {i};
let r = b[p+2];
let g = b[p+4];
let b = b[p+6];
let n = if !dev {b[p + 1] as usize} else {i};
let r = b[p + 2];
let g = b[p + 4];
let b = b[p + 6];
if n >= clut.len() {
return Err(err_msg("bad clut index"));
}
if n >= clut.len() {return Err(err_msg("bad clut index"));}
clut[n] = Color{r, g, b, a: 255};
p += 8;
@ -261,8 +301,12 @@ pub fn read_rle(b: &[u8], pitch: usize, ln: bool) -> ResultS<(Vec<u8>, usize)>
{
let mut p = 0;
let mut o = Vec::with_capacity(pitch);
let sz = if pitch > 250 {(b.c_u16b(0)? as usize + 2, p += 2).0}
else {(b[0] as usize + 1, p += 1).0};
let sz = if pitch > 250 {
(b.c_u16b(0)? as usize + 2, p += 2).0
} else {
(b[0] as usize + 1, p += 1).0
};
while p < sz {
let szf = b[(p, p += 1).0];
@ -278,8 +322,11 @@ pub fn read_rle(b: &[u8], pitch: usize, ln: bool) -> ResultS<(Vec<u8>, usize)>
}
}
if o.len() == pitch {Ok((o, p))}
else {Err(err_msg("incorrect size for compressed scanline"))}
if o.len() == pitch {
Ok((o, p))
} else {
Err(err_msg("incorrect size for compressed scanline"))
}
}
/// Read a sequence of packed RLE data.
@ -289,28 +336,38 @@ fn read_rle_data<F, N>(cmp: bool, len: usize, out: &mut Vec<u8>, mut read: F)
{
if cmp {
let d = read();
for _ in 0..len {for v in d.iter() {out.push(*v);}}
for _ in 0..len {
for v in d.iter() {
out.push(*v);
}
}
} else {
for _ in 0..len {let d = read(); for v in d.iter() {out.push(*v);}}
for _ in 0..len {
let d = read();
for v in d.iter() {
out.push(*v);
}
}
}
}
/// Expand packed pixel data based on bit depth.
pub fn expand_data(b: Vec<u8>, depth: u16) -> ResultS<Vec<u8>>
{
let mut o = Vec::with_capacity(match depth {
let mut o =
Vec::with_capacity(match depth {
4 => b.len() * 2,
2 => b.len() * 4,
1 => b.len() * 8,
_ => return Err(err_msg("invalid bit depth"))
_ => return Err(err_msg("invalid bit depth")),
});
for ch in b {
match depth {
4 => for i in 1..=0 {o.push(ch >> i * 4 & 0xFu8);}, // 2 nibbles
2 => for i in 3..=0 {o.push(ch >> i * 2 & 0x3u8);}, // 4 dibits
1 => for i in 7..=0 {o.push(ch >> i * 1 & 0x1u8);}, // 8 bits
_ => return Err(err_msg("invalid bit depth"))
4 => {for i in 1..=0 {o.push(ch >> i * 4 & 0xFu8);}} // 2 nibbles
2 => {for i in 3..=0 {o.push(ch >> i * 2 & 0x3u8);}} // 4 dibits
1 => {for i in 7..=0 {o.push(ch >> i * 1 & 0x1u8);}} // 8 bits
_ => return Err(err_msg("invalid bit depth")),
}
}

View File

@ -4,12 +4,12 @@ use std::fmt;
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
{
// flags = b.c_u16b( 0)?;
let ttype = b.c_u16b( 2)?;
let pdata = b.c_i16b( 4)?;
let start = b.c_u16b( 6)? as usize;
let size = b.c_u16b( 8)? as usize;
let ttype = b.c_u16b(2)?;
let pdata = b.c_i16b(4)?;
let start = b.c_u16b(6)? as usize;
let size = b.c_u16b(8)? as usize;
let lines = b.c_u16b(10)?;
let text = mac_roman_conv(&text[start..start+size]);
let text = mac_roman_conv(&text[start..start + size]);
let ttype = GroupType::from_repr(ttype)?;
Ok(Group{ttype, pdata, lines, text})
@ -21,13 +21,13 @@ fn read_face(b: &[u8]) -> ResultS<Face>
let face = b.c_u16b(2)?;
let color = b.c_u16b(4)?;
Ok(Face{start, face, color})
Ok(Face { start, face, color })
}
fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
{
const SIZE_GROUP: usize = 12;
const SIZE_FACE : usize = 6;
const SIZE_FACE: usize = 6;
let end = b.c_u16b(0)? as usize;
let encoded = b.c_u16b(2)? & 1 != 0;
@ -36,13 +36,17 @@ fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
let face_n = b.c_u16b(8)? as usize;
let mut groups = Vec::with_capacity(group_n);
let mut faces = Vec::with_capacity( face_n);
let mut faces = Vec::with_capacity(face_n);
let mut p = 10; // size of header
let text_st = p + SIZE_GROUP * group_n + SIZE_FACE * face_n;
let text = &b[text_st..end];
let text = if encoded {fuck_string(text)} else {text.to_vec()};
let text = if encoded {
fuck_string(text)
} else {
text.to_vec()
};
for _ in 0..group_n {
groups.push(read_group(&b[p..], &text)?);
@ -127,7 +131,9 @@ impl fmt::Debug for Group
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
write!(f, "Group{{{:?} {} {}", self.ttype, self.pdata, self.lines)?;
if self.text.len() != 0 {write!(f, ";\n{}", self.text)?;}
if self.text.len() != 0 {
write!(f, ";\n{}", self.text)?;
}
write!(f, "}}")
}
}

View File

@ -7,10 +7,12 @@ impl Wad<'_>
{
pub fn new(b: &[u8]) -> ResultS<Wad>
{
if b.len() < 128 {return Err(err_msg("not enough data for Wad header"));}
if b.len() < 128 {
return Err(err_msg("not enough data for Wad header"));
}
let wadver = b.c_u16b( 0)?;
let dataver = b.c_u16b( 2)?;
let wadver = b.c_u16b(0)?;
let dataver = b.c_u16b(2)?;
let origname = mac_roman_conv(&b[4..68]);
// crc = b.c_u32b(68)?;
let dirofs = b.c_u32b(72)? as usize;
@ -21,25 +23,35 @@ impl Wad<'_>
// parent = b.c_u32b(84)?;
let wadver = Ver::from_repr(wadver)?;
let is_old = match wadver {Ver::Base => true, _ => false};
let is_old = match wadver {
Ver::Base => true,
_ => false,
};
let entsize = if !is_old {10} else {8 };
let cnksize = if !is_old {16} else {12};
if entsize != wentsize {return Err(err_msg("invalid entry size"));}
if cnksize != wcnksize {return Err(err_msg("invalid chunk size"));}
if entsize != wentsize {
return Err(err_msg("invalid entry size"));
}
if cnksize != wcnksize {
return Err(err_msg("invalid chunk size"));
}
let mut entries = EntryMap::new();
let mut p = dirofs;
for i in 0..numents {
let offset = b.c_u32b(p )? as usize;
let size = b.c_u32b(p+4)? as usize;
let index = if !is_old {b.c_u16b(p+8)?} else {i as u16};
let offset = b.c_u32b(p)? as usize;
let size = b.c_u32b(p + 4)? as usize;
let index = if !is_old {b.c_u16b(p + 8)?} else {i as u16};
if offset + size > b.len() {return Err(err_msg("not enough data for entry"));}
if offset + size > b.len() {
return Err(err_msg("not enough data for entry"));
}
let chunks = get_chunks(&b[offset..offset+size], cnksize)?;
let appdata = &b[p..p+appsize];
let chunks = get_chunks(&b[offset..offset + size], cnksize)?;
let appdata = &b[p..p + appsize];
entries.insert(index, Entry{chunks, appdata});
@ -56,9 +68,9 @@ fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
let mut p = 0;
while p < b.len() {
let iden = b.c_iden(p )?;
let iden = b.c_iden(p)?;
// ofs = b.c_u32b(p+ 4)?;
let size = b.c_u32b(p+ 8)? as usize;
let size = b.c_u32b(p + 8)? as usize;
// pofs = b.c_u32b(p+12)?;
let beg = p + cnksize;
let end = beg + size;
@ -69,14 +81,14 @@ fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
Ok(chunks)
}
type Chunk <'a> = &'a[u8];
type Chunk<'a> = &'a [u8];
type ChunkMap<'a> = BTreeMap<Ident, Chunk<'a>>;
type EntryMap<'a> = BTreeMap<u16 , Entry<'a>>;
type EntryMap<'a> = BTreeMap<u16, Entry<'a>>;
pub struct Entry<'a>
{
pub chunks: ChunkMap<'a>,
pub appdata: &'a[u8],
pub appdata: &'a [u8],
}
#[derive(Debug)]
@ -105,8 +117,12 @@ impl fmt::Debug for Entry<'_>
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
write!(f, "Entry{{ ")?;
for (iden, _) in &self.chunks {write!(f, "{} ", mac_roman_conv(iden))?;}
if self.appdata.len() != 0 {write!(f, "\nappdata: {:?} ", self.appdata)?;}
for (iden, _) in &self.chunks {
write!(f, "{} ", mac_roman_conv(iden))?;
}
if self.appdata.len() != 0 {
write!(f, "\nappdata: {:?} ", self.appdata)?;
}
write!(f, "}}")
}
}

View File

@ -1,5 +1,4 @@
use maraiah::durandal::image::Color;
use maraiah::marathon::pict::get_clut;
use maraiah::{durandal::image::Color, marathon::pict::get_clut};
#[test]
fn get_clut_must_process_this()

View File

@ -5,7 +5,7 @@ use maraiah::marathon::machdr::*;
#[test]
fn macbin_must_process_this()
{
assert_eq!( check_macbin(INPUT_MACBIN), Some(128));
assert_eq!(check_macbin(INPUT_MACBIN), Some(128));
assert_eq!(try_mac_header(INPUT_MACBIN), 128);
}