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,19 +137,21 @@ 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]
fn fx32_basic_ops()
{
let seven_div_2 = 3 << Fx32::FRACBITS | Fx32::FRACMASK / 2 + 1;
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(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]
@ -109,9 +165,10 @@ fn fx32_overflow()
#[test]
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!("{}", 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");
}
// EOF

View File

@ -15,8 +15,8 @@ pub struct Color
/// Image with width and height.
pub struct Image
{
w: usize,
h: usize,
w: usize,
h: usize,
pub cr: Vec<Color>,
}
@ -26,8 +26,8 @@ impl Color
pub fn from_r5g5b5(rgb: u16) -> Color
{
let r = rgb >> 10 & 0x1f;
let g = rgb >> 5 & 0x1f;
let b = rgb & 0x1f;
let g = rgb >> 5 & 0x1f;
let b = rgb & 0x1f;
Color{r: (r << 3 | r >> 2) as u8,
g: (g << 3 | g >> 2) as u8,
b: (b << 3 | b >> 2) as u8,
@ -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() {
@ -44,11 +49,19 @@ pub fn to_binsize(n: u64) -> String
pub fn fuck_string(s: &[u8]) -> Vec<u8>
{
let mut v = s.to_vec();
let l = s.len();
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,64 +72,58 @@ 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()
{
assert_eq!(to_binsize(0), "empty");
assert_eq!(to_binsize(1), "1 byte");
assert_eq!(to_binsize(2), "2 bytes");
assert_eq!(to_binsize(999), "999 bytes");
assert_eq!(to_binsize(1000), "1kB");
assert_eq!(to_binsize(1000 * 7), "7kB");
assert_eq!(to_binsize(1000 * 1000), "1MB");
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 7), "7GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000), "1TB");
assert_eq!(to_binsize(0), "empty");
assert_eq!(to_binsize(1), "1 byte");
assert_eq!(to_binsize(2), "2 bytes");
assert_eq!(to_binsize(999), "999 bytes");
assert_eq!(to_binsize(1000), "1kB");
assert_eq!(to_binsize(1000 * 7), "7kB");
assert_eq!(to_binsize(1000 * 1000), "1MB");
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 7), "7GB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000), "1TB");
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
}

View File

@ -1,16 +1,19 @@
//! 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 {}
impl PrimInt for u16 {}
impl PrimInt for i16 {}
impl PrimInt for u32 {}
impl PrimInt for i32 {}
impl PrimInt for u64 {}
impl PrimInt for i64 {}
impl PrimInt for u8 {}
impl PrimInt for i8 {}
impl PrimInt for u16 {}
impl PrimInt for i16 {}
impl PrimInt for u32 {}
impl PrimInt for i32 {}
impl PrimInt for u64 {}
impl PrimInt for i64 {}
impl PrimInt for u128 {}
impl PrimInt for i128 {}

View File

@ -1,10 +1,11 @@
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<()>
{
let out = fs::File::create(fname)?;
let out = fs::File::create(fname)?;
let mut out = io::BufWriter::new(out);
write!(&mut out, "P3\n{} {}\n255\n", im.w(), im.h())?;
@ -22,41 +23,41 @@ fn write_ppm(fname: &str, im: &Image) -> io::Result<()>
fn read_chunk(cid: &Ident, cnk: &[u8], eid: u16) -> ResultS<()>
{
match cid {
b"PICT" => {
let im = pict::load_pict(cnk)?;
println!("entry {} has PICT {}x{}", eid, im.w(), im.h());
write_ppm(&format!("out/{}.ppm", eid), &im)?;
}
b"Minf" => {
let minf = map::Minf::chunk(cnk)?;
println!("entry {} has {:#?}", eid, minf);
}
b"EPNT" => {
let epnt = map::Endpoint::chunk(cnk)?;
println!("entry {} has EPNT {:#?}", eid, epnt);
}
b"PNTS" => {
let epnt = map::Point::chunk(cnk)?;
println!("entry {} has PNTS {:#?}", eid, epnt);
}
b"LINS" => {
let line = map::Line::chunk(cnk)?;
println!("entry {} has LINS {:#?}", eid, line);
}
b"SIDS" => {
let line = map::Side::chunk(cnk)?;
println!("entry {} has SIDS {:#?}", eid, line);
}
b"term" => {
let term = term::Terminal::chunk(cnk)?;
println!("entry {} has term {:#?}", eid, term);
}
cid => {
let fname = format!("out/{:04}{}.bin", eid, mac_roman_conv(cid));
let out = fs::File::create(&fname)?;
let mut out = io::BufWriter::new(out);
out.write(cnk)?;
}
b"PICT" => {
let im = pict::load_pict(cnk)?;
println!("entry {} has PICT {}x{}", eid, im.w(), im.h());
write_ppm(&format!("out/{}.ppm", eid), &im)?;
}
b"Minf" => {
let minf = map::Minf::chunk(cnk)?;
println!("entry {} has {:#?}", eid, minf);
}
b"EPNT" => {
let epnt = map::Endpoint::chunk(cnk)?;
println!("entry {} has EPNT {:#?}", eid, epnt);
}
b"PNTS" => {
let epnt = map::Point::chunk(cnk)?;
println!("entry {} has PNTS {:#?}", eid, epnt);
}
b"LINS" => {
let line = map::Line::chunk(cnk)?;
println!("entry {} has LINS {:#?}", eid, line);
}
b"SIDS" => {
let line = map::Side::chunk(cnk)?;
println!("entry {} has SIDS {:#?}", eid, line);
}
b"term" => {
let term = term::Terminal::chunk(cnk)?;
println!("entry {} has term {:#?}", eid, term);
}
cid => {
let fname = format!("out/{:04}{}.bin", eid, mac_roman_conv(cid));
let out = fs::File::create(&fname)?;
let mut out = io::BufWriter::new(out);
out.write(cnk)?;
}
}
Ok(())
@ -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"))
"wad:" => process_wad(b),
"shp:" => process_shp(b),
_ => 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
@ -20,12 +20,12 @@ impl Chunked<Endpoint> for Endpoint
fn read(b: &[u8]) -> ResultS<Endpoint>
{
let flags = b.c_u16b(0)?;
let adj_hi = b.c_i16b(2)?;
let adj_lo = b.c_i16b(4)?;
let pos = Point::read(&b[6..10])?;
let flags = b.c_u16b(0)?;
let adj_hi = b.c_i16b(2)?;
let adj_lo = b.c_i16b(4)?;
let pos = Point::read(&b[6..10])?;
let support = b.c_u16b(14)?;
let flags = EndpointFlags::from_bits_truncate(flags);
let flags = EndpointFlags::from_bits_truncate(flags);
Ok(Endpoint{flags, adj_hi, adj_lo, pos, support})
}
}
@ -38,7 +38,7 @@ impl Chunked<Line> for Line
{
let epnt_f = b.c_u16b(0)?;
let epnt_b = b.c_u16b(2)?;
let flags = b.c_u16b(4)?;
let flags = b.c_u16b(4)?;
let length = b.c_i16b(6)?;
let adj_hi = b.c_i16b(8)?;
let adj_lo = b.c_i16b(10)?;
@ -46,7 +46,7 @@ impl Chunked<Line> for Line
let side_b = b.c_u16b(14)?;
let poly_f = b.c_u16b(16)?;
let poly_b = b.c_u16b(18)?;
let flags = LineFlags::from_bits_truncate(flags);
let flags = LineFlags::from_bits_truncate(flags);
Ok(Line{flags, length, adj_hi, adj_lo, epnt_f, epnt_b, side_f, side_b,
poly_f, poly_b})
}
@ -54,7 +54,7 @@ impl Chunked<Line> for Line
fn read_side_tex(b: &[u8]) -> ResultS<SideTex>
{
let offs = Point::read(&b[0..4])?;
let offs = Point::read(&b[0..4])?;
let tex_id = b.c_u16b(4)?;
let tex_id = if tex_id == 65535 {None} else {Some(tex_id)};
Ok(SideTex{offs, tex_id})
@ -66,11 +66,11 @@ impl Chunked<Side> for Side
fn read(b: &[u8]) -> ResultS<Side>
{
let stype = b.c_u16b(0)?;
let flags = b.c_u16b(2)?;
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 stype = b.c_u16b(0)?;
let flags = b.c_u16b(2)?;
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])?;
let ex_trigh = Point::read(&b[26..30])?;
let ex_bleft = Point::read(&b[30..34])?;
@ -80,9 +80,9 @@ impl Chunked<Side> for Side
let xfer_pri = b.c_u16b(42)?;
let xfer_sec = b.c_u16b(44)?;
let xfer_tra = b.c_u16b(46)?;
let shade = b.c_u32b(48)?;
let flags = SideFlags::from_bits_truncate(flags);
let shade = Fx32::from_bits(shade);
let shade = b.c_u32b(48)?;
let flags = SideFlags::from_bits_truncate(flags);
let shade = Fx32::from_bits(shade);
Ok(Side{stype, flags, tex_pri, tex_sec, tex_tra, ex_tleft, ex_trigh,
ex_bleft, ex_brigh, paneltyp, paneldat, xfer_pri, xfer_sec,
xfer_tra, shade})
@ -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);
@ -119,17 +119,17 @@ pub struct Point
#[derive(Debug)]
pub struct Endpoint
{
flags: EndpointFlags,
adj_hi: Unit,
adj_lo: Unit,
pos: Point,
flags: EndpointFlags,
adj_hi: Unit,
adj_lo: Unit,
pos: Point,
support: u16,
}
#[derive(Debug)]
pub struct Line
{
flags: LineFlags,
flags: LineFlags,
length: Unit,
adj_hi: Unit,
adj_lo: Unit,
@ -144,18 +144,18 @@ pub struct Line
#[derive(Debug)]
pub struct SideTex
{
offs: Point,
offs: Point,
tex_id: Option<u16>,
}
#[derive(Debug)]
pub struct Side
{
stype: u16,
flags: SideFlags,
tex_pri: SideTex,
tex_sec: SideTex,
tex_tra: SideTex,
stype: u16,
flags: SideFlags,
tex_pri: SideTex,
tex_sec: SideTex,
tex_tra: SideTex,
ex_tleft: Point,
ex_trigh: Point,
ex_bleft: Point,
@ -165,7 +165,7 @@ pub struct Side
xfer_pri: u16,
xfer_sec: u16,
xfer_tra: u16,
shade: Fx32,
shade: Fx32,
}
#[derive(Debug)]
@ -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;
// version = b.c_u16b(p+10)?;
let pack_typ = b.c_u16b(p+12)?;
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)?;
// 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)?;
// comp_n = b.c_u16b(p+30)?;
// comp_d = b.c_u16b(p+32)?;
// format = b.c_u16b(p+26)?;
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)?;
// 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,98 +58,108 @@ 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) ||
(pack_typ == PACK_RLE32 && depth == 32);
let rle = pack_typ == PACK_DEFAULT ||
(pack_typ == PACK_RLE16 && depth == 16) ||
(pack_typ == PACK_RLE32 && depth == 32);
let pitch = (pitch_fl & 0x3fff) as usize;
match depth {
1 | 2 | 4 | 8 => {
let clut = clut.ok_or_else(|| err_msg("no clut in indexed mode"))?;
if pitch < 8 && depth == 8 {
// uncompressed 8-bit colormap indices
for _ in 0..h {
for _ in 0..w {
im.cr.push(clut[b[(p, p += 1).0] as usize].clone());
1 | 2 | 4 | 8 => {
let clut = clut.ok_or_else(|| err_msg("no clut in indexed mode"))?;
if pitch < 8 && depth == 8 {
// uncompressed 8-bit colormap indices
for _ in 0..h {
for _ in 0..w {
im.cr.push(clut[b[(p, p += 1).0] as usize].clone());
}
}
Ok(im)
} else if rle {
// RLE compressed 1, 2, 4 or 8 bit colormap indices
for _ in 0..h {
let (d, pp) = read_rle(&b[p..], pitch, false)?;
let d = if depth < 8 {expand_data(d, depth)?} else {d};
p += pp;
for x in 0..w {
im.cr.push(clut[d[x] as usize].clone());
}
}
Ok(im)
} else {
Err(err_msg("invalid configuration"))
}
Ok(im)
} else if rle {
// RLE compressed 1, 2, 4 or 8 bit colormap indices
for _ in 0..h {
let (d, pp) = read_rle(&b[p..], pitch, false)?;
let d = if depth < 8 {expand_data(d, depth)?} else {d};
p += pp;
for x in 0..w {im.cr.push(clut[d[x] as usize].clone());}
}
Ok(im)
} else {
Err(err_msg("invalid configuration"))
}
},
16 =>
if pitch < 8 || pack_typ == PACK_NONE {
// uncompressed R5G5B5
for _ in 0..h {
for _ in 0..w {
im.cr.push(Color::from_r5g5b5(b.c_u16b((p, p += 2).0)?));
16 => {
if pitch < 8 || pack_typ == PACK_NONE {
// uncompressed R5G5B5
for _ in 0..h {
for _ in 0..w {
im.cr.push(Color::from_r5g5b5(b.c_u16b((p, p += 2).0)?));
}
}
}
Ok(im)
} else if rle {
// RLE compressed R5G5B5
for _ in 0..h {
let (d, pp) = read_rle(&b[p..], pitch, true)?;
Ok(im)
} else if rle {
// RLE compressed R5G5B5
for _ in 0..h {
let (d, pp) = read_rle(&b[p..], pitch, true)?;
p += pp;
p += pp;
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 =>
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]);
p += 3;
im.cr.push(Color{r, g, b, a: 255});
for x in 0..w {
im.cr.push(Color::from_r5g5b5(d.c_u16b(x * 2)?));
}
}
Ok(im)
} else {
Err(err_msg("invalid configuration"))
}
Ok(im)
} else if rle {
// RLE compressed RGB8
let pitch = pitch - w; // remove padding byte from pitch
for _ in 0..h {
let (d, pp) = read_rle(&b[p..], pitch, false)?;
p += pp;
for x in 0..w {
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});
}
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]);
p += 3;
im.cr.push(Color{r, g, b, a: 255});
}
}
}
Ok(im)
} else {
Err(err_msg("invalid configuration"))
},
_ => Err(err_msg("invalid bit depth"))
Ok(im)
} else if rle {
// RLE compressed RGB8
let pitch = pitch - w; // remove padding byte from pitch
for _ in 0..h {
let (d, pp) = read_rle(&b[p..], pitch, false)?;
p += pp;
for x in 0..w {
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});
}
}
Ok(im)
} else {
Err(err_msg("invalid configuration"))
}
}
_ => Err(err_msg("invalid bit depth")),
}
}
@ -156,11 +173,11 @@ pub fn read_quicktime_c(_im: Image, _b: &[u8]) -> ResultS<Image>
pub fn load_pict(b: &[u8]) -> ResultS<Image>
{
// size = b.c_u16b(0)?;
// top = b.c_u16b(2)?;
// top = b.c_u16b(2)?;
// left = b.c_u16b(4)?;
let h = b.c_u16b(6)? as usize;
let w = b.c_u16b(8)? as usize;
let im = Image::new(w, h);
let h = b.c_u16b(6)? as usize;
let w = b.c_u16b(8)? as usize;
let im = Image::new(w, h);
let mut p = 10; // size of header
@ -168,62 +185,82 @@ 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
// help i'm trapped in an awful metafile format from the 80s
0x0000 | // NoOp
0x001c | // HiliteMode
0x001e | // DefHilite
0x0038 | // FrameSameRect
0x0039 | // PaintSameRect
0x003a | // EraseSameRect
0x003b | // InvertSameRect
0x003c | // FillSameRect
0x8000 | // Reserved
0x8100 => (), // Reserved
0x0003 | // TxFont
0x0004 | // TxFace
0x0005 | // TxMode
0x0008 | // PnMode
0x000d | // TxSize
0x0011 | // VersionOp
0x0015 | // PnLocHFrac
0x0016 | // ChExtra
0x0023 | // ShortLineFrom
0x00a0 | // ShortComment
0x02ff => p += 2, // Version
0x0006 | // SpExtra
0x0007 | // PnSize
0x000b | // OvSize
0x000c | // Origin
0x000e | // FgCol
0x000f | // BkCol
0x0021 => p += 4, // LineFrom
0x001a | // RGBFgCol
0x001b | // RGBBkCol
0x001d | // TxRatio
0x0022 => p += 6, // ShortLine
0x0002 | // BkPat
0x0009 | // PnPat
0x0010 | // TxRatio
0x0020 | // Line
0x002e | // GlyphState
0x0030 | // FrameRect
0x0031 | // PaintRect
0x0032 | // EraseRect
0x0033 | // InvertRect
0x0034 => p += 8, // FillRect
0x002d => p += 10, // LineJustify
0x0c00 => p += 24, // HeaderOp
0x0001 => p += (b.c_u16b(p )? & !1) as usize, // Clip
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"))
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
0x001e | // DefHilite
0x0038 | // FrameSameRect
0x0039 | // PaintSameRect
0x003a | // EraseSameRect
0x003b | // InvertSameRect
0x003c | // FillSameRect
0x8000 | // Reserved
0x8100 => (), // Reserved
0x0003 | // TxFont
0x0004 | // TxFace
0x0005 | // TxMode
0x0008 | // PnMode
0x000d | // TxSize
0x0011 | // VersionOp
0x0015 | // PnLocHFrac
0x0016 | // ChExtra
0x0023 | // ShortLineFrom
0x00a0 | // ShortComment
0x02ff => p += 2, // Version
0x0006 | // SpExtra
0x0007 | // PnSize
0x000b | // OvSize
0x000c | // Origin
0x000e | // FgCol
0x000f | // BkCol
0x0021 => p += 4, // LineFrom
0x001a | // RGBFgCol
0x001b | // RGBBkCol
0x001d | // TxRatio
0x0022 => p += 6, // ShortLine
0x0002 | // BkPat
0x0009 | // PnPat
0x0010 | // TxRatio
0x0020 | // Line
0x002e | // GlyphState
0x0030 | // FrameRect
0x0031 | // PaintRect
0x0032 | // EraseRect
0x0033 | // InvertRect
0x0034 => p += 8, // FillRect
0x002d => p += 10, // LineJustify
0x0c00 => p += 24, // HeaderOp
0x0001 => p += (b.c_u16b(p )? & !1) as usize, // Clip
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"));
}
}
}
@ -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 {
4 => b.len() * 2,
2 => b.len() * 4,
1 => b.len() * 8,
_ => return Err(err_msg("invalid bit 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")),
});
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})
@ -18,31 +18,35 @@ fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
fn read_face(b: &[u8]) -> ResultS<Face>
{
let start = b.c_u16b(0)? as usize;
let face = b.c_u16b(2)?;
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 end = b.c_u16b(0)? as usize;
let encoded = b.c_u16b(2)? & 1 != 0;
let lines = b.c_u16b(4)?;
let lines = b.c_u16b(4)?;
let group_n = b.c_u16b(6)? as usize;
let face_n = b.c_u16b(8)? as usize;
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)?);
@ -77,16 +81,16 @@ impl Chunker<Vec<Terminal>> for Terminal
#[derive(Debug)]
pub struct Terminal
{
lines: u16,
lines: u16,
groups: Vec<Group>,
faces: Vec<Face>,
faces: Vec<Face>,
}
#[derive(Debug)]
pub struct Face
{
start: usize,
face: u16,
face: u16,
color: u16,
}
@ -95,7 +99,7 @@ pub struct Group
ttype: GroupType,
pdata: i16,
lines: u16,
text: String,
text: String,
}
c_enum! {
@ -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,39 +7,51 @@ 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;
let numents = b.c_u16b(76)? as usize;
let appsize = b.c_u16b(78)? as usize;
// crc = b.c_u32b(68)?;
let dirofs = b.c_u32b(72)? as usize;
let numents = b.c_u16b(76)? as usize;
let appsize = b.c_u16b(78)? as usize;
let wcnksize = b.c_u16b(80)? as usize;
let wentsize = b.c_u16b(82)? as usize;
// parent = b.c_u32b(84)?;
let wadver = Ver::from_repr(wadver)?;
// 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,12 +68,12 @@ fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
let mut p = 0;
while p < b.len() {
let iden = b.c_iden(p )?;
// ofs = b.c_u32b(p+ 4)?;
let size = b.c_u32b(p+ 8)? as usize;
let iden = b.c_iden(p)?;
// ofs = b.c_u32b(p+ 4)?;
let size = b.c_u32b(p + 8)? as usize;
// pofs = b.c_u32b(p+12)?;
let beg = p + cnksize;
let end = beg + size;
let beg = p + cnksize;
let end = beg + size;
chunks.insert(iden, &b[beg..end]);
p = end;
}
@ -69,24 +81,24 @@ 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 chunks: ChunkMap<'a>,
pub appdata: &'a [u8],
}
#[derive(Debug)]
pub struct Wad<'a>
{
wadver: Ver,
dataver: u16,
origname: String,
appsize: usize,
pub entries: EntryMap<'a>,
wadver: Ver,
dataver: u16,
origname: String,
appsize: usize,
pub entries: EntryMap<'a>,
}
c_enum! {
@ -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);
}