partially format code with rustfmt
parent
dd5bf03252
commit
6d99752e6e
|
@ -2,6 +2,7 @@ binop_separator = "Back"
|
||||||
brace_style = "AlwaysNextLine"
|
brace_style = "AlwaysNextLine"
|
||||||
condense_wildcard_suffixes = true
|
condense_wildcard_suffixes = true
|
||||||
enum_discrim_align_threshold = 40
|
enum_discrim_align_threshold = 40
|
||||||
|
fn_single_line = true
|
||||||
format_doc_comments = true
|
format_doc_comments = true
|
||||||
format_macro_matchers = true
|
format_macro_matchers = true
|
||||||
format_strings = true
|
format_strings = true
|
||||||
|
|
|
@ -12,23 +12,63 @@ pub trait BinUtil
|
||||||
fn c_u16b(&self, i: usize) -> ResultS<u16>;
|
fn c_u16b(&self, i: usize) -> ResultS<u16>;
|
||||||
|
|
||||||
fn c_i32b(&self, i: usize) -> ResultS<i32>
|
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>
|
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
|
// Optional
|
||||||
fn o_iden(&self, i: usize) -> Option<Ident> {self.c_iden(i).ok()}
|
fn o_iden(&self, i: usize) -> Option<Ident>
|
||||||
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()}
|
self.c_iden(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_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
|
// Unchecked
|
||||||
fn b_iden(&self, i: usize) -> Ident {self.c_iden(i).unwrap()}
|
fn b_iden(&self, i: usize) -> Ident
|
||||||
fn b_u32b(&self, i: usize) -> u32 {self.c_u32b(i).unwrap()}
|
{
|
||||||
fn b_u16b(&self, i: usize) -> u16 {self.c_u16b(i).unwrap()}
|
self.c_iden(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_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]
|
impl BinUtil for [u8]
|
||||||
|
@ -45,7 +85,10 @@ impl BinUtil for [u8]
|
||||||
fn c_u32b(&self, i: usize) -> ResultS<u32>
|
fn c_u32b(&self, i: usize) -> ResultS<u32>
|
||||||
{
|
{
|
||||||
if i + 3 < self.len() {
|
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 {
|
} else {
|
||||||
Err(err_msg("not enough data"))
|
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_u32b(n: u32) -> [u8; 4]
|
||||||
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)}
|
n.to_be_bytes()
|
||||||
pub fn d_i16b(n: i16) -> [u8; 2] {d_u16b(n as u16)}
|
}
|
||||||
|
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
|
// EOF
|
||||||
|
|
|
@ -2,21 +2,27 @@
|
||||||
|
|
||||||
fn crc_accum(a: u32) -> u32
|
fn crc_accum(a: u32) -> u32
|
||||||
{
|
{
|
||||||
if a & 1 == 1 {0xedb88320 ^ a >> 1}
|
if a & 1 == 1 {
|
||||||
else {a >> 1}
|
0xedb88320 ^ a >> 1
|
||||||
|
} else {
|
||||||
|
a >> 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crc_init() -> [u32; 256]
|
fn crc_init() -> [u32; 256]
|
||||||
{
|
{
|
||||||
let mut t = [0; 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
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn crc32(b: &[u8], s: u32) -> u32
|
pub fn crc32(b: &[u8], s: u32) -> u32
|
||||||
{
|
{
|
||||||
let t = crc_init();
|
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]
|
#[test]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Error handling.
|
//! Error handling.
|
||||||
|
|
||||||
pub use failure::{Error, Fail, err_msg};
|
pub use failure::{err_msg, Error, Fail};
|
||||||
|
|
||||||
use crate::durandal::traits::PrimInt;
|
use crate::durandal::traits::PrimInt;
|
||||||
use std::fmt;
|
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
|
impl<T> fmt::Display for ReprError<T> where T: PrimInt
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
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
|
impl<T> fmt::Debug for ReprError<T> where T: PrimInt
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
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>;
|
pub type ResultS<T> = Result<T, Error>;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::{fmt, fmt::Write, ops};
|
use std::{fmt::{self, Write},
|
||||||
|
ops};
|
||||||
|
|
||||||
pub struct Fx32(i32);
|
pub struct Fx32(i32);
|
||||||
|
|
||||||
|
@ -8,55 +9,108 @@ impl Fx32
|
||||||
const FRACMASK: u32 = 0xFFFF;
|
const FRACMASK: u32 = 0xFFFF;
|
||||||
const ONE: i32 = 1 << Fx32::FRACBITS;
|
const ONE: i32 = 1 << Fx32::FRACBITS;
|
||||||
|
|
||||||
pub fn to_bits(&self) -> u32 {self.0 as u32}
|
pub fn to_bits(&self) -> 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)}
|
self.0 as u32
|
||||||
|
}
|
||||||
|
|
||||||
pub fn integ(&self) -> i16 {(self.0 >> Fx32::FRACBITS) as i16}
|
pub fn set_bits(&mut self, bits: u32)
|
||||||
pub fn fract(&self) -> u16 {(self.0 as u32 & Fx32::FRACMASK) as u16}
|
{
|
||||||
|
self.0 = bits as i32
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mul_i(&self, n: i32) -> Fx32 {Fx32(self.0 * n)}
|
pub fn from_bits(bits: u32) -> Fx32
|
||||||
pub fn div_i(&self, n: i32) -> Fx32 {Fx32(self.0 / n)}
|
{
|
||||||
|
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
|
impl ops::Add for Fx32
|
||||||
{
|
{
|
||||||
type Output = 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
|
impl ops::Sub for Fx32
|
||||||
{
|
{
|
||||||
type Output = 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
|
impl ops::Mul for Fx32
|
||||||
{
|
{
|
||||||
type Output = Fx32;
|
type Output = Fx32;
|
||||||
|
|
||||||
fn mul(self, o: Fx32) -> 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
|
impl ops::Div for Fx32
|
||||||
{
|
{
|
||||||
type Output = Fx32;
|
type Output = Fx32;
|
||||||
|
|
||||||
fn div(self, o: Fx32) -> 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
|
impl ops::Neg for Fx32
|
||||||
{
|
{
|
||||||
type Output = Fx32;
|
type Output = Fx32;
|
||||||
fn neg(self) -> Fx32 {Fx32(-self.0)}
|
|
||||||
|
fn neg(self) -> Fx32
|
||||||
|
{
|
||||||
|
Fx32(-self.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Not for Fx32
|
impl ops::Not for Fx32
|
||||||
{
|
{
|
||||||
type Output = Fx32;
|
type Output = Fx32;
|
||||||
fn not(self) -> Fx32 {Fx32(!self.0)}
|
|
||||||
|
fn not(self) -> Fx32
|
||||||
|
{
|
||||||
|
Fx32(!self.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Fx32
|
impl fmt::Display for Fx32
|
||||||
|
@ -83,19 +137,21 @@ impl fmt::Display for Fx32
|
||||||
impl fmt::Debug for Fx32
|
impl fmt::Debug for Fx32
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
||||||
{fmt::Display::fmt(self, f)}
|
{
|
||||||
|
fmt::Display::fmt(self, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fx32_basic_ops()
|
fn fx32_basic_ops()
|
||||||
{
|
{
|
||||||
let seven_div_2 = 3 << Fx32::FRACBITS | Fx32::FRACMASK / 2 + 1;
|
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(1) + 1.into()).to_bits(), 2 << Fx32::FRACBITS);
|
||||||
assert_eq!((Fx32::from(2) - 1.into()).to_bits(), 1 << 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) * 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) / 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]
|
#[test]
|
||||||
|
@ -109,9 +165,10 @@ fn fx32_overflow()
|
||||||
#[test]
|
#[test]
|
||||||
fn fx32_printing()
|
fn fx32_printing()
|
||||||
{
|
{
|
||||||
assert_eq!(format!("{}", Fx32::from(6)), "6.0");
|
assert_eq!(format!("{}", Fx32::from(6)), "6.0");
|
||||||
assert_eq!(format!("{}", Fx32::from(7).div_i(2)), "3.5");
|
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
|
// EOF
|
||||||
|
|
|
@ -15,8 +15,8 @@ pub struct Color
|
||||||
/// Image with width and height.
|
/// Image with width and height.
|
||||||
pub struct Image
|
pub struct Image
|
||||||
{
|
{
|
||||||
w: usize,
|
w: usize,
|
||||||
h: usize,
|
h: usize,
|
||||||
pub cr: Vec<Color>,
|
pub cr: Vec<Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ impl Color
|
||||||
pub fn from_r5g5b5(rgb: u16) -> Color
|
pub fn from_r5g5b5(rgb: u16) -> Color
|
||||||
{
|
{
|
||||||
let r = rgb >> 10 & 0x1f;
|
let r = rgb >> 10 & 0x1f;
|
||||||
let g = rgb >> 5 & 0x1f;
|
let g = rgb >> 5 & 0x1f;
|
||||||
let b = rgb & 0x1f;
|
let b = rgb & 0x1f;
|
||||||
Color{r: (r << 3 | r >> 2) as u8,
|
Color{r: (r << 3 | r >> 2) as u8,
|
||||||
g: (g << 3 | g >> 2) as u8,
|
g: (g << 3 | g >> 2) as u8,
|
||||||
b: (b << 3 | b >> 2) as u8,
|
b: (b << 3 | b >> 2) as u8,
|
||||||
|
@ -39,10 +39,19 @@ impl Image
|
||||||
{
|
{
|
||||||
/// Creates a new Image structure.
|
/// Creates a new Image structure.
|
||||||
pub fn new(w: usize, h: usize) -> Image
|
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 w(&self) -> usize
|
||||||
pub fn h(&self) -> usize {self.h}
|
{
|
||||||
|
self.w
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn h(&self) -> usize
|
||||||
|
{
|
||||||
|
self.h
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<(usize, usize)> for Image
|
impl Index<(usize, usize)> for Image
|
||||||
|
@ -50,13 +59,17 @@ impl Index<(usize, usize)> for Image
|
||||||
type Output = Color;
|
type Output = Color;
|
||||||
|
|
||||||
fn index(&self, (x, y): (usize, usize)) -> &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
|
impl IndexMut<(usize, usize)> for Image
|
||||||
{
|
{
|
||||||
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Color
|
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
|
// EOF
|
||||||
|
|
|
@ -11,8 +11,11 @@ pub fn dump_mem(b: &[u8])
|
||||||
p = 0;
|
p = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.is_ascii_graphic() {eprint!(" {} ", c as char);}
|
if c.is_ascii_graphic() {
|
||||||
else {eprint!("{:02X} ", c);}
|
eprint!(" {} ", c as char);
|
||||||
|
} else {
|
||||||
|
eprint!("{:02X} ", c);
|
||||||
|
}
|
||||||
|
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +29,9 @@ pub fn to_binsize(n: u64) -> String
|
||||||
const NAMES: [&str; 4] = ["kB", "MB", "GB", "TB"];
|
const NAMES: [&str; 4] = ["kB", "MB", "GB", "TB"];
|
||||||
|
|
||||||
// empty size
|
// empty size
|
||||||
if n == 0 {return String::from("empty");}
|
if n == 0 {
|
||||||
|
return String::from("empty");
|
||||||
|
}
|
||||||
|
|
||||||
// terabytes, gigabytes, megabytes, kilobytes
|
// terabytes, gigabytes, megabytes, kilobytes
|
||||||
for i in (1..=4).rev() {
|
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>
|
pub fn fuck_string(s: &[u8]) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut v = s.to_vec();
|
let mut v = s.to_vec();
|
||||||
let l = s.len();
|
let l = s.len();
|
||||||
let mut p = 0;
|
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 {
|
||||||
for _ in 0..l % 4 {v[p] ^= 0xfe; p += 1;}
|
p += 2;
|
||||||
|
v[p] ^= 0xfe;
|
||||||
|
v[p + 1] ^= 0xed;
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
for _ in 0..l % 4 {
|
||||||
|
v[p] ^= 0xfe;
|
||||||
|
p += 1;
|
||||||
|
}
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
@ -59,64 +72,58 @@ pub fn mac_roman_conv(s: &[u8]) -> String
|
||||||
let mut v = String::with_capacity(s.len());
|
let mut v = String::with_capacity(s.len());
|
||||||
|
|
||||||
for i in 0..s.len() {
|
for i in 0..s.len() {
|
||||||
if s[i] == 0 {break;}
|
if s[i] == 0 {
|
||||||
else if s[i] & 0x80 != 0 {v.push(TR[s[i] as usize & 0x7f]);}
|
break;
|
||||||
else if s[i] == b'\r' {v.push('\n');}
|
} else if s[i] & 0x80 != 0 {
|
||||||
else {v.push(s[i] as char);}
|
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
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
const TR: [char; 128] = [
|
const TR: [char; 128] =
|
||||||
'\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}',
|
['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}',
|
||||||
'\u{00d1}', '\u{00d6}', '\u{00dc}', '\u{00e1}',
|
'\u{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
|
||||||
'\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
|
'\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}', '\u{00ea}', '\u{00eb}',
|
||||||
'\u{00e5}', '\u{00e7}', '\u{00e9}', '\u{00e8}',
|
'\u{00ed}', '\u{00ec}', '\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}',
|
||||||
'\u{00ea}', '\u{00eb}', '\u{00ed}', '\u{00ec}',
|
'\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}', '\u{00fa}', '\u{00f9}',
|
||||||
'\u{00ee}', '\u{00ef}', '\u{00f1}', '\u{00f3}',
|
'\u{00fb}', '\u{00fc}', '\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}',
|
||||||
'\u{00f2}', '\u{00f4}', '\u{00f6}', '\u{00f5}',
|
'\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}', '\u{00ae}', '\u{00a9}',
|
||||||
'\u{00fa}', '\u{00f9}', '\u{00fb}', '\u{00fc}',
|
'\u{2122}', '\u{00b4}', '\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}',
|
||||||
'\u{2020}', '\u{00b0}', '\u{00a2}', '\u{00a3}',
|
'\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}', '\u{00a5}', '\u{00b5}',
|
||||||
'\u{00a7}', '\u{2022}', '\u{00b6}', '\u{00df}',
|
'\u{2202}', '\u{2211}', '\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}',
|
||||||
'\u{00ae}', '\u{00a9}', '\u{2122}', '\u{00b4}',
|
'\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}', '\u{00bf}', '\u{00a1}',
|
||||||
'\u{00a8}', '\u{2260}', '\u{00c6}', '\u{00d8}',
|
'\u{00ac}', '\u{221a}', '\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}',
|
||||||
'\u{221e}', '\u{00b1}', '\u{2264}', '\u{2265}',
|
'\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}', '\u{00c3}', '\u{00d5}',
|
||||||
'\u{00a5}', '\u{00b5}', '\u{2202}', '\u{2211}',
|
'\u{0152}', '\u{0153}', '\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}',
|
||||||
'\u{220f}', '\u{03c0}', '\u{222b}', '\u{00aa}',
|
'\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}', '\u{00ff}', '\u{0178}',
|
||||||
'\u{00ba}', '\u{03a9}', '\u{00e6}', '\u{00f8}',
|
'\u{2044}', '\u{20ac}', '\u{2039}', '\u{203a}', '\u{fb01}', '\u{fb02}',
|
||||||
'\u{00bf}', '\u{00a1}', '\u{00ac}', '\u{221a}',
|
'\u{2021}', '\u{00b7}', '\u{201a}', '\u{201e}', '\u{2030}', '\u{00c2}',
|
||||||
'\u{0192}', '\u{2248}', '\u{2206}', '\u{00ab}',
|
'\u{00ca}', '\u{00c1}', '\u{00cb}', '\u{00c8}', '\u{00cd}', '\u{00ce}',
|
||||||
'\u{00bb}', '\u{2026}', '\u{00a0}', '\u{00c0}',
|
'\u{00cf}', '\u{00cc}', '\u{00d3}', '\u{00d4}', '\u{f8ff}', '\u{00d2}',
|
||||||
'\u{00c3}', '\u{00d5}', '\u{0152}', '\u{0153}',
|
'\u{00da}', '\u{00db}', '\u{00d9}', '\u{0131}', '\u{02c6}', '\u{02dc}',
|
||||||
'\u{2013}', '\u{2014}', '\u{201c}', '\u{201d}',
|
'\u{00af}', '\u{02d8}', '\u{02d9}', '\u{02da}', '\u{00b8}', '\u{02dd}',
|
||||||
'\u{2018}', '\u{2019}', '\u{00f7}', '\u{25ca}',
|
'\u{02db}', '\u{02c7}'];
|
||||||
'\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]
|
#[test]
|
||||||
fn to_binsize_integrals()
|
fn to_binsize_integrals()
|
||||||
{
|
{
|
||||||
assert_eq!(to_binsize(0), "empty");
|
assert_eq!(to_binsize(0), "empty");
|
||||||
assert_eq!(to_binsize(1), "1 byte");
|
assert_eq!(to_binsize(1), "1 byte");
|
||||||
assert_eq!(to_binsize(2), "2 bytes");
|
assert_eq!(to_binsize(2), "2 bytes");
|
||||||
assert_eq!(to_binsize(999), "999 bytes");
|
assert_eq!(to_binsize(999), "999 bytes");
|
||||||
assert_eq!(to_binsize(1000), "1kB");
|
assert_eq!(to_binsize(1000), "1kB");
|
||||||
assert_eq!(to_binsize(1000 * 7), "7kB");
|
assert_eq!(to_binsize(1000 * 7), "7kB");
|
||||||
assert_eq!(to_binsize(1000 * 1000), "1MB");
|
assert_eq!(to_binsize(1000 * 1000), "1MB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
|
assert_eq!(to_binsize(1000 * 1000 * 7), "7MB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
|
assert_eq!(to_binsize(1000 * 1000 * 1000), "1GB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 1000 * 7), "7GB");
|
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), "1TB");
|
||||||
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
|
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
//! Traits for basic types, because Rust doesn't provide them.
|
//! Traits for basic types, because Rust doesn't provide them.
|
||||||
|
|
||||||
/// Any primitive integer type.
|
/// 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 u8 {}
|
||||||
impl PrimInt for i8 {}
|
impl PrimInt for i8 {}
|
||||||
impl PrimInt for u16 {}
|
impl PrimInt for u16 {}
|
||||||
impl PrimInt for i16 {}
|
impl PrimInt for i16 {}
|
||||||
impl PrimInt for u32 {}
|
impl PrimInt for u32 {}
|
||||||
impl PrimInt for i32 {}
|
impl PrimInt for i32 {}
|
||||||
impl PrimInt for u64 {}
|
impl PrimInt for u64 {}
|
||||||
impl PrimInt for i64 {}
|
impl PrimInt for i64 {}
|
||||||
impl PrimInt for u128 {}
|
impl PrimInt for u128 {}
|
||||||
impl PrimInt for i128 {}
|
impl PrimInt for i128 {}
|
||||||
|
|
||||||
|
|
117
src/main.rs
117
src/main.rs
|
@ -1,10 +1,11 @@
|
||||||
use maraiah::durandal::{bin::*, chunk::*, err::*, image::Image, text::*};
|
use maraiah::{durandal::{bin::*, chunk::*, err::*, image::Image, text::*},
|
||||||
use maraiah::marathon::{machdr, map, pict, term, wad};
|
marathon::{machdr, map, pict, term, wad}};
|
||||||
use std::{io, io::Write, fs, env};
|
use std::{env, fs,
|
||||||
|
io::{self, Write}};
|
||||||
|
|
||||||
fn write_ppm(fname: &str, im: &Image) -> io::Result<()>
|
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);
|
let mut out = io::BufWriter::new(out);
|
||||||
|
|
||||||
write!(&mut out, "P3\n{} {}\n255\n", im.w(), im.h())?;
|
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<()>
|
fn read_chunk(cid: &Ident, cnk: &[u8], eid: u16) -> ResultS<()>
|
||||||
{
|
{
|
||||||
match cid {
|
match cid {
|
||||||
b"PICT" => {
|
b"PICT" => {
|
||||||
let im = pict::load_pict(cnk)?;
|
let im = pict::load_pict(cnk)?;
|
||||||
println!("entry {} has PICT {}x{}", eid, im.w(), im.h());
|
println!("entry {} has PICT {}x{}", eid, im.w(), im.h());
|
||||||
write_ppm(&format!("out/{}.ppm", eid), &im)?;
|
write_ppm(&format!("out/{}.ppm", eid), &im)?;
|
||||||
}
|
}
|
||||||
b"Minf" => {
|
b"Minf" => {
|
||||||
let minf = map::Minf::chunk(cnk)?;
|
let minf = map::Minf::chunk(cnk)?;
|
||||||
println!("entry {} has {:#?}", eid, minf);
|
println!("entry {} has {:#?}", eid, minf);
|
||||||
}
|
}
|
||||||
b"EPNT" => {
|
b"EPNT" => {
|
||||||
let epnt = map::Endpoint::chunk(cnk)?;
|
let epnt = map::Endpoint::chunk(cnk)?;
|
||||||
println!("entry {} has EPNT {:#?}", eid, epnt);
|
println!("entry {} has EPNT {:#?}", eid, epnt);
|
||||||
}
|
}
|
||||||
b"PNTS" => {
|
b"PNTS" => {
|
||||||
let epnt = map::Point::chunk(cnk)?;
|
let epnt = map::Point::chunk(cnk)?;
|
||||||
println!("entry {} has PNTS {:#?}", eid, epnt);
|
println!("entry {} has PNTS {:#?}", eid, epnt);
|
||||||
}
|
}
|
||||||
b"LINS" => {
|
b"LINS" => {
|
||||||
let line = map::Line::chunk(cnk)?;
|
let line = map::Line::chunk(cnk)?;
|
||||||
println!("entry {} has LINS {:#?}", eid, line);
|
println!("entry {} has LINS {:#?}", eid, line);
|
||||||
}
|
}
|
||||||
b"SIDS" => {
|
b"SIDS" => {
|
||||||
let line = map::Side::chunk(cnk)?;
|
let line = map::Side::chunk(cnk)?;
|
||||||
println!("entry {} has SIDS {:#?}", eid, line);
|
println!("entry {} has SIDS {:#?}", eid, line);
|
||||||
}
|
}
|
||||||
b"term" => {
|
b"term" => {
|
||||||
let term = term::Terminal::chunk(cnk)?;
|
let term = term::Terminal::chunk(cnk)?;
|
||||||
println!("entry {} has term {:#?}", eid, term);
|
println!("entry {} has term {:#?}", eid, term);
|
||||||
}
|
}
|
||||||
cid => {
|
cid => {
|
||||||
let fname = format!("out/{:04}{}.bin", eid, mac_roman_conv(cid));
|
let fname = format!("out/{:04}{}.bin", eid, mac_roman_conv(cid));
|
||||||
let out = fs::File::create(&fname)?;
|
let out = fs::File::create(&fname)?;
|
||||||
let mut out = io::BufWriter::new(out);
|
let mut out = io::BufWriter::new(out);
|
||||||
out.write(cnk)?;
|
out.write(cnk)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -79,11 +80,11 @@ fn process_wad(b: &[u8]) -> ResultS<()>
|
||||||
|
|
||||||
fn collection(b: &[u8]) -> ResultS<()>
|
fn collection(b: &[u8]) -> ResultS<()>
|
||||||
{
|
{
|
||||||
let version = b.c_u16b(0 )?;
|
let version = b.c_u16b(0)?;
|
||||||
let dt_type = b.c_u16b(2 )?;
|
let dt_type = b.c_u16b(2)?;
|
||||||
let flags = b.c_u16b(4 )?;
|
let flags = b.c_u16b(4)?;
|
||||||
let colors = b.c_u16b(6 )?;
|
let colors = b.c_u16b(6)?;
|
||||||
let clu_num = b.c_u16b(8 )?;
|
let clu_num = b.c_u16b(8)?;
|
||||||
let clu_ofs = b.c_u32b(10)?;
|
let clu_ofs = b.c_u32b(10)?;
|
||||||
let seq_num = b.c_u16b(14)?;
|
let seq_num = b.c_u16b(14)?;
|
||||||
let seq_ofs = b.c_u32b(16)?;
|
let seq_ofs = b.c_u32b(16)?;
|
||||||
|
@ -109,7 +110,9 @@ fn collection(b: &[u8]) -> ResultS<()>
|
||||||
dbg!(size);
|
dbg!(size);
|
||||||
eprintln!("[end of collection]");
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -118,12 +121,12 @@ fn process_shp(b: &[u8]) -> ResultS<()>
|
||||||
{
|
{
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
let p = 32 * i;
|
let p = 32 * i;
|
||||||
let status = b.c_u16b(p+0 )?;
|
let status = b.c_u16b(p + 0)?;
|
||||||
let flags = b.c_u16b(p+2 )?;
|
let flags = b.c_u16b(p + 2)?;
|
||||||
let offset_lo = b.c_u32b(p+4 )? as usize;
|
let offset_lo = b.c_u32b(p + 4)? as usize;
|
||||||
let length_lo = b.c_u32b(p+8 )? as usize;
|
let length_lo = b.c_u32b(p + 8)? as usize;
|
||||||
let offset_hi = b.c_u32b(p+12)? as usize;
|
let offset_hi = b.c_u32b(p + 12)? as usize;
|
||||||
let length_hi = b.c_u32b(p+16)? as usize;
|
let length_hi = b.c_u32b(p + 16)? as usize;
|
||||||
dbg!(i);
|
dbg!(i);
|
||||||
dbg!(status);
|
dbg!(status);
|
||||||
dbg!(flags);
|
dbg!(flags);
|
||||||
|
@ -133,11 +136,11 @@ fn process_shp(b: &[u8]) -> ResultS<()>
|
||||||
dbg!(length_hi);
|
dbg!(length_hi);
|
||||||
if offset_lo != u32::max_value() as usize {
|
if offset_lo != u32::max_value() as usize {
|
||||||
eprintln!("collection {} has lo-res frames", i);
|
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 {
|
if offset_hi != u32::max_value() as usize {
|
||||||
eprintln!("collection {} has hi-res frames", i);
|
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 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)..];
|
let b = &mm[machdr::try_mac_header(&mm)..];
|
||||||
|
|
||||||
match typ {
|
match typ {
|
||||||
"wad:" => process_wad(b),
|
"wad:" => process_wad(b),
|
||||||
"shp:" => process_shp(b),
|
"shp:" => process_shp(b),
|
||||||
_ => Err(err_msg("invalid file type specified on commandline"))
|
_ => Err(err_msg("invalid file type specified on commandline")),
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,21 @@ use crate::durandal::bin::*;
|
||||||
pub fn check_apple_single(b: &[u8]) -> Option<usize>
|
pub fn check_apple_single(b: &[u8]) -> Option<usize>
|
||||||
{
|
{
|
||||||
// check magic numbers
|
// check magic numbers
|
||||||
if b[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)
|
// get the resource fork (entity 1)
|
||||||
let num = b.o_u16b(24)? as usize;
|
let num = b.o_u16b(24)? as usize;
|
||||||
for i in 0..num {
|
for i in 0..num {
|
||||||
let p = 26 + 12 * i;
|
let p = 26 + 12 * i;
|
||||||
let ent = b.o_u32b(p )?;
|
let ent = b.o_u32b(p)?;
|
||||||
let ofs = b.o_u32b(p+4)? as usize;
|
let ofs = b.o_u32b(p + 4)? as usize;
|
||||||
let len = b.o_u32b(p+8)? 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
|
// no resource fork
|
||||||
|
@ -27,7 +31,9 @@ pub fn check_apple_single(b: &[u8]) -> Option<usize>
|
||||||
pub fn check_macbin(b: &[u8]) -> Option<usize>
|
pub fn check_macbin(b: &[u8]) -> Option<usize>
|
||||||
{
|
{
|
||||||
// check legacy version, length, zero fill, and macbin2 version
|
// 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;
|
let mut crc = 0;
|
||||||
|
|
||||||
|
@ -35,21 +41,31 @@ pub fn check_macbin(b: &[u8]) -> Option<usize>
|
||||||
for i in 0..124 {
|
for i in 0..124 {
|
||||||
for j in 8..16 {
|
for j in 8..16 {
|
||||||
let d = b[i] as (u16) << j;
|
let d = b[i] as (u16) << j;
|
||||||
if (d ^ crc) & 0x8000 != 0 {crc = crc << 1 ^ 0x1021;}
|
if (d ^ crc) & 0x8000 != 0 {
|
||||||
else {crc <<= 1;}
|
crc = crc << 1 ^ 0x1021;
|
||||||
|
} else {
|
||||||
|
crc <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ok, resource fork follows
|
// 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
|
/// 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.)
|
/// offset from the start of the header to the resource fork (if one is found.)
|
||||||
pub fn try_mac_header(b: &[u8]) -> usize
|
pub fn try_mac_header(b: &[u8]) -> usize
|
||||||
{
|
{
|
||||||
if let Some(ofs) = check_macbin(b) {ofs}
|
if let Some(ofs) = check_macbin(b) {
|
||||||
else {check_apple_single(b).unwrap_or(0)}
|
ofs
|
||||||
|
} else {
|
||||||
|
check_apple_single(b).unwrap_or(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use bitflags::bitflags;
|
|
||||||
use crate::durandal::{bin::*, chunk::*, err::*, fx32::*, text::mac_roman_conv};
|
use crate::durandal::{bin::*, chunk::*, err::*, fx32::*, text::mac_roman_conv};
|
||||||
|
use bitflags::bitflags;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
impl Chunked<Point> for Point
|
impl Chunked<Point> for Point
|
||||||
|
@ -20,12 +20,12 @@ impl Chunked<Endpoint> for Endpoint
|
||||||
|
|
||||||
fn read(b: &[u8]) -> ResultS<Endpoint>
|
fn read(b: &[u8]) -> ResultS<Endpoint>
|
||||||
{
|
{
|
||||||
let flags = b.c_u16b(0)?;
|
let flags = b.c_u16b(0)?;
|
||||||
let adj_hi = b.c_i16b(2)?;
|
let adj_hi = b.c_i16b(2)?;
|
||||||
let adj_lo = b.c_i16b(4)?;
|
let adj_lo = b.c_i16b(4)?;
|
||||||
let pos = Point::read(&b[6..10])?;
|
let pos = Point::read(&b[6..10])?;
|
||||||
let support = b.c_u16b(14)?;
|
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})
|
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_f = b.c_u16b(0)?;
|
||||||
let epnt_b = b.c_u16b(2)?;
|
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 length = b.c_i16b(6)?;
|
||||||
let adj_hi = b.c_i16b(8)?;
|
let adj_hi = b.c_i16b(8)?;
|
||||||
let adj_lo = b.c_i16b(10)?;
|
let adj_lo = b.c_i16b(10)?;
|
||||||
|
@ -46,7 +46,7 @@ impl Chunked<Line> for Line
|
||||||
let side_b = b.c_u16b(14)?;
|
let side_b = b.c_u16b(14)?;
|
||||||
let poly_f = b.c_u16b(16)?;
|
let poly_f = b.c_u16b(16)?;
|
||||||
let poly_b = b.c_u16b(18)?;
|
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,
|
Ok(Line{flags, length, adj_hi, adj_lo, epnt_f, epnt_b, side_f, side_b,
|
||||||
poly_f, poly_b})
|
poly_f, poly_b})
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ impl Chunked<Line> for Line
|
||||||
|
|
||||||
fn read_side_tex(b: &[u8]) -> ResultS<SideTex>
|
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 = b.c_u16b(4)?;
|
||||||
let tex_id = if tex_id == 65535 {None} else {Some(tex_id)};
|
let tex_id = if tex_id == 65535 {None} else {Some(tex_id)};
|
||||||
Ok(SideTex{offs, tex_id})
|
Ok(SideTex{offs, tex_id})
|
||||||
|
@ -66,11 +66,11 @@ impl Chunked<Side> for Side
|
||||||
|
|
||||||
fn read(b: &[u8]) -> ResultS<Side>
|
fn read(b: &[u8]) -> ResultS<Side>
|
||||||
{
|
{
|
||||||
let stype = b.c_u16b(0)?;
|
let stype = b.c_u16b(0)?;
|
||||||
let flags = b.c_u16b(2)?;
|
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_sec = read_side_tex(&b[10..16])?;
|
||||||
let tex_tra = read_side_tex(&b[16..22])?;
|
let tex_tra = read_side_tex(&b[16..22])?;
|
||||||
let ex_tleft = Point::read(&b[22..26])?;
|
let ex_tleft = Point::read(&b[22..26])?;
|
||||||
let ex_trigh = Point::read(&b[26..30])?;
|
let ex_trigh = Point::read(&b[26..30])?;
|
||||||
let ex_bleft = Point::read(&b[30..34])?;
|
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_pri = b.c_u16b(42)?;
|
||||||
let xfer_sec = b.c_u16b(44)?;
|
let xfer_sec = b.c_u16b(44)?;
|
||||||
let xfer_tra = b.c_u16b(46)?;
|
let xfer_tra = b.c_u16b(46)?;
|
||||||
let shade = b.c_u32b(48)?;
|
let shade = b.c_u32b(48)?;
|
||||||
let flags = SideFlags::from_bits_truncate(flags);
|
let flags = SideFlags::from_bits_truncate(flags);
|
||||||
let shade = Fx32::from_bits(shade);
|
let shade = Fx32::from_bits(shade);
|
||||||
Ok(Side{stype, flags, tex_pri, tex_sec, tex_tra, ex_tleft, ex_trigh,
|
Ok(Side{stype, flags, tex_pri, tex_sec, tex_tra, ex_tleft, ex_trigh,
|
||||||
ex_bleft, ex_brigh, paneltyp, paneldat, xfer_pri, xfer_sec,
|
ex_bleft, ex_brigh, paneltyp, paneldat, xfer_pri, xfer_sec,
|
||||||
xfer_tra, shade})
|
xfer_tra, shade})
|
||||||
|
@ -93,11 +93,11 @@ impl Chunker<Minf> for Minf
|
||||||
{
|
{
|
||||||
fn chunk(b: &[u8]) -> ResultS<Minf>
|
fn chunk(b: &[u8]) -> ResultS<Minf>
|
||||||
{
|
{
|
||||||
let env_code = b.c_u16b( 0)?;
|
let env_code = b.c_u16b(0)?;
|
||||||
let physi_id = b.c_u16b( 2)?;
|
let physi_id = b.c_u16b(2)?;
|
||||||
let music_id = b.c_u16b( 4)?;
|
let music_id = b.c_u16b(4)?;
|
||||||
let msn_flag = b.c_u16b( 6)?;
|
let msn_flag = b.c_u16b(6)?;
|
||||||
let env_flag = b.c_u16b( 8)?;
|
let env_flag = b.c_u16b(8)?;
|
||||||
let levelnam = mac_roman_conv(&b[18..84]);
|
let levelnam = mac_roman_conv(&b[18..84]);
|
||||||
let ent_flag = b.c_u32b(84)?;
|
let ent_flag = b.c_u32b(84)?;
|
||||||
let msn_flag = MsnFlags::from_bits_truncate(msn_flag);
|
let msn_flag = MsnFlags::from_bits_truncate(msn_flag);
|
||||||
|
@ -119,17 +119,17 @@ pub struct Point
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Endpoint
|
pub struct Endpoint
|
||||||
{
|
{
|
||||||
flags: EndpointFlags,
|
flags: EndpointFlags,
|
||||||
adj_hi: Unit,
|
adj_hi: Unit,
|
||||||
adj_lo: Unit,
|
adj_lo: Unit,
|
||||||
pos: Point,
|
pos: Point,
|
||||||
support: u16,
|
support: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Line
|
pub struct Line
|
||||||
{
|
{
|
||||||
flags: LineFlags,
|
flags: LineFlags,
|
||||||
length: Unit,
|
length: Unit,
|
||||||
adj_hi: Unit,
|
adj_hi: Unit,
|
||||||
adj_lo: Unit,
|
adj_lo: Unit,
|
||||||
|
@ -144,18 +144,18 @@ pub struct Line
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SideTex
|
pub struct SideTex
|
||||||
{
|
{
|
||||||
offs: Point,
|
offs: Point,
|
||||||
tex_id: Option<u16>,
|
tex_id: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Side
|
pub struct Side
|
||||||
{
|
{
|
||||||
stype: u16,
|
stype: u16,
|
||||||
flags: SideFlags,
|
flags: SideFlags,
|
||||||
tex_pri: SideTex,
|
tex_pri: SideTex,
|
||||||
tex_sec: SideTex,
|
tex_sec: SideTex,
|
||||||
tex_tra: SideTex,
|
tex_tra: SideTex,
|
||||||
ex_tleft: Point,
|
ex_tleft: Point,
|
||||||
ex_trigh: Point,
|
ex_trigh: Point,
|
||||||
ex_bleft: Point,
|
ex_bleft: Point,
|
||||||
|
@ -165,7 +165,7 @@ pub struct Side
|
||||||
xfer_pri: u16,
|
xfer_pri: u16,
|
||||||
xfer_sec: u16,
|
xfer_sec: u16,
|
||||||
xfer_tra: u16,
|
xfer_tra: u16,
|
||||||
shade: Fx32,
|
shade: Fx32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -262,7 +262,9 @@ bitflags! {
|
||||||
impl fmt::Debug for Point
|
impl fmt::Debug for Point
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
||||||
{write!(f, "({}, {})", self.x, self.y)}
|
{
|
||||||
|
write!(f, "({}, {})", self.x, self.y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -4,39 +4,46 @@ use crate::durandal::{bin::*, err::*, image::*};
|
||||||
use generic_array::*;
|
use generic_array::*;
|
||||||
|
|
||||||
const PACK_DEFAULT: u16 = 0;
|
const PACK_DEFAULT: u16 = 0;
|
||||||
const PACK_NONE : u16 = 1;
|
const PACK_NONE: u16 = 1;
|
||||||
const PACK_NOPAD : u16 = 2;
|
const PACK_NOPAD: u16 = 2;
|
||||||
const PACK_RLE16 : u16 = 3;
|
const PACK_RLE16: u16 = 3;
|
||||||
const PACK_RLE32 : u16 = 4;
|
const PACK_RLE32: u16 = 4;
|
||||||
|
|
||||||
/// Process a CopyBits operation.
|
/// 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 mut p = if !packed {4} else {0};
|
||||||
|
|
||||||
let (w, h) = (im.w(), im.h());
|
let (w, h) = (im.w(), im.h());
|
||||||
|
|
||||||
let pitch_fl = b.c_u16b(p )?;
|
let pitch_fl = b.c_u16b(p)?;
|
||||||
let top = b.c_u16b(p+ 2)? as usize;
|
let top = b.c_u16b(p + 2)? as usize;
|
||||||
let left = b.c_u16b(p+ 4)? as usize;
|
let left = b.c_u16b(p + 4)? as usize;
|
||||||
let bottom = b.c_u16b(p+ 6)? as usize;
|
let bottom = b.c_u16b(p + 6)? as usize;
|
||||||
let right = b.c_u16b(p+ 8)? as usize;
|
let right = b.c_u16b(p + 8)? as usize;
|
||||||
// version = b.c_u16b(p+10)?;
|
// 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)?;
|
// pack_siz = b.c_u32b(p+14)?;
|
||||||
// horz_dpi = b.c_u32b(p+18)?;
|
// horz_dpi = b.c_u32b(p+18)?;
|
||||||
// vert_dpi = b.c_u32b(p+22)?;
|
// vert_dpi = b.c_u32b(p+22)?;
|
||||||
// format = b.c_u16b(p+26)?;
|
// 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_n = b.c_u16b(p+30)?;
|
||||||
// comp_d = b.c_u16b(p+32)?;
|
// comp_d = b.c_u16b(p+32)?;
|
||||||
// planeofs = b.c_u32b(p+34)?;
|
// 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
|
if pitch_fl & 0x8000 == 0 {
|
||||||
{return Err(err_msg("PICT1 not supported"));}
|
return Err(err_msg("PICT1 not supported"));
|
||||||
if right - left != w || bottom - top != h
|
}
|
||||||
{return Err(err_msg("image bounds are incorrect"));}
|
|
||||||
|
if right - left != w || bottom - top != h {
|
||||||
|
return Err(err_msg("image bounds are incorrect"));
|
||||||
|
}
|
||||||
|
|
||||||
p += 46; // size of header
|
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
|
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 ||
|
let rle = pack_typ == PACK_DEFAULT ||
|
||||||
(pack_typ == PACK_RLE16 && depth == 16) ||
|
(pack_typ == PACK_RLE16 && depth == 16) ||
|
||||||
(pack_typ == PACK_RLE32 && depth == 32);
|
(pack_typ == PACK_RLE32 && depth == 32);
|
||||||
|
|
||||||
let pitch = (pitch_fl & 0x3fff) as usize;
|
let pitch = (pitch_fl & 0x3fff) as usize;
|
||||||
|
|
||||||
match depth {
|
match depth {
|
||||||
1 | 2 | 4 | 8 => {
|
1 | 2 | 4 | 8 => {
|
||||||
let clut = clut.ok_or_else(|| err_msg("no clut in indexed mode"))?;
|
let clut = clut.ok_or_else(|| err_msg("no clut in indexed mode"))?;
|
||||||
if pitch < 8 && depth == 8 {
|
if pitch < 8 && depth == 8 {
|
||||||
// uncompressed 8-bit colormap indices
|
// uncompressed 8-bit colormap indices
|
||||||
for _ in 0..h {
|
for _ in 0..h {
|
||||||
for _ in 0..w {
|
for _ in 0..w {
|
||||||
im.cr.push(clut[b[(p, p += 1).0] as usize].clone());
|
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 => {
|
||||||
16 =>
|
if pitch < 8 || pack_typ == PACK_NONE {
|
||||||
if pitch < 8 || pack_typ == PACK_NONE {
|
// uncompressed R5G5B5
|
||||||
// uncompressed R5G5B5
|
for _ in 0..h {
|
||||||
for _ in 0..h {
|
for _ in 0..w {
|
||||||
for _ in 0..w {
|
im.cr.push(Color::from_r5g5b5(b.c_u16b((p, p += 2).0)?));
|
||||||
im.cr.push(Color::from_r5g5b5(b.c_u16b((p, p += 2).0)?));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(im)
|
Ok(im)
|
||||||
} else if rle {
|
} else if rle {
|
||||||
// RLE compressed R5G5B5
|
// RLE compressed R5G5B5
|
||||||
for _ in 0..h {
|
for _ in 0..h {
|
||||||
let (d, pp) = read_rle(&b[p..], pitch, true)?;
|
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)?));}
|
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});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(im)
|
||||||
|
} else {
|
||||||
|
Err(err_msg("invalid configuration"))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Ok(im)
|
32 => {
|
||||||
} else if rle {
|
if pitch < 8 || pack_typ == PACK_NONE || pack_typ == PACK_NOPAD {
|
||||||
// RLE compressed RGB8
|
// uncompressed RGB8 or XRGB8
|
||||||
let pitch = pitch - w; // remove padding byte from pitch
|
for _ in 0..h {
|
||||||
for _ in 0..h {
|
for _ in 0..w {
|
||||||
let (d, pp) = read_rle(&b[p..], pitch, false)?;
|
if pack_typ != PACK_NOPAD {
|
||||||
|
p += 1;
|
||||||
p += pp;
|
}
|
||||||
|
let (r, g, b) = (b[p], b[p + 1], b[p + 2]);
|
||||||
for x in 0..w {
|
p += 3;
|
||||||
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});
|
||||||
im.cr.push(Color{r, g, b, a: 255});
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(im)
|
Ok(im)
|
||||||
} else {
|
} else if rle {
|
||||||
Err(err_msg("invalid configuration"))
|
// RLE compressed RGB8
|
||||||
},
|
let pitch = pitch - w; // remove padding byte from pitch
|
||||||
_ => Err(err_msg("invalid bit depth"))
|
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>
|
pub fn load_pict(b: &[u8]) -> ResultS<Image>
|
||||||
{
|
{
|
||||||
// size = b.c_u16b(0)?;
|
// size = b.c_u16b(0)?;
|
||||||
// top = b.c_u16b(2)?;
|
// top = b.c_u16b(2)?;
|
||||||
// left = b.c_u16b(4)?;
|
// left = b.c_u16b(4)?;
|
||||||
let h = b.c_u16b(6)? as usize;
|
let h = b.c_u16b(6)? as usize;
|
||||||
let w = b.c_u16b(8)? as usize;
|
let w = b.c_u16b(8)? as usize;
|
||||||
let im = Image::new(w, h);
|
let im = Image::new(w, h);
|
||||||
|
|
||||||
let mut p = 10; // size of header
|
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)?;
|
let op = b.c_u16b((p, p += 2).0)?;
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
0x0098 => return read_bitmap_area(im, &b[p..], true, false), // PackBitsRect
|
0x0098 => {
|
||||||
0x0099 => return read_bitmap_area(im, &b[p..], true, true ), // PackBitsRgn
|
// PackBitsRect
|
||||||
0x009a => return read_bitmap_area(im, &b[p..], false, false), // DirectBitsRect
|
return read_bitmap_area(im, &b[p..], true, false);
|
||||||
0x009b => return read_bitmap_area(im, &b[p..], false, true ), // DirectBitsRgn
|
}
|
||||||
0x8200 => return read_quicktime_c(im, &b[p..]), // CompressedQuickTime
|
0x0099 => {
|
||||||
0x00ff => break, // OpEndPic
|
// PackBitsRgn
|
||||||
// help i'm trapped in an awful metafile format from the 80s
|
return read_bitmap_area(im, &b[p..], true, true);
|
||||||
0x0000 | // NoOp
|
}
|
||||||
0x001c | // HiliteMode
|
0x009a => {
|
||||||
0x001e | // DefHilite
|
// DirectBitsRect
|
||||||
0x0038 | // FrameSameRect
|
return read_bitmap_area(im, &b[p..], false, false);
|
||||||
0x0039 | // PaintSameRect
|
}
|
||||||
0x003a | // EraseSameRect
|
0x009b => {
|
||||||
0x003b | // InvertSameRect
|
// DirectBitsRgn
|
||||||
0x003c | // FillSameRect
|
return read_bitmap_area(im, &b[p..], false, true);
|
||||||
0x8000 | // Reserved
|
}
|
||||||
0x8100 => (), // Reserved
|
0x8200 => {
|
||||||
0x0003 | // TxFont
|
// CompressedQuickTime
|
||||||
0x0004 | // TxFace
|
return read_quicktime_c(im, &b[p..]);
|
||||||
0x0005 | // TxMode
|
}
|
||||||
0x0008 | // PnMode
|
0x00ff => {
|
||||||
0x000d | // TxSize
|
// OpEndPic
|
||||||
0x0011 | // VersionOp
|
break;
|
||||||
0x0015 | // PnLocHFrac
|
}
|
||||||
0x0016 | // ChExtra
|
// help i'm trapped in an awful metafile format from the 80s
|
||||||
0x0023 | // ShortLineFrom
|
0x0000 | // NoOp
|
||||||
0x00a0 | // ShortComment
|
0x001c | // HiliteMode
|
||||||
0x02ff => p += 2, // Version
|
0x001e | // DefHilite
|
||||||
0x0006 | // SpExtra
|
0x0038 | // FrameSameRect
|
||||||
0x0007 | // PnSize
|
0x0039 | // PaintSameRect
|
||||||
0x000b | // OvSize
|
0x003a | // EraseSameRect
|
||||||
0x000c | // Origin
|
0x003b | // InvertSameRect
|
||||||
0x000e | // FgCol
|
0x003c | // FillSameRect
|
||||||
0x000f | // BkCol
|
0x8000 | // Reserved
|
||||||
0x0021 => p += 4, // LineFrom
|
0x8100 => (), // Reserved
|
||||||
0x001a | // RGBFgCol
|
0x0003 | // TxFont
|
||||||
0x001b | // RGBBkCol
|
0x0004 | // TxFace
|
||||||
0x001d | // TxRatio
|
0x0005 | // TxMode
|
||||||
0x0022 => p += 6, // ShortLine
|
0x0008 | // PnMode
|
||||||
0x0002 | // BkPat
|
0x000d | // TxSize
|
||||||
0x0009 | // PnPat
|
0x0011 | // VersionOp
|
||||||
0x0010 | // TxRatio
|
0x0015 | // PnLocHFrac
|
||||||
0x0020 | // Line
|
0x0016 | // ChExtra
|
||||||
0x002e | // GlyphState
|
0x0023 | // ShortLineFrom
|
||||||
0x0030 | // FrameRect
|
0x00a0 | // ShortComment
|
||||||
0x0031 | // PaintRect
|
0x02ff => p += 2, // Version
|
||||||
0x0032 | // EraseRect
|
0x0006 | // SpExtra
|
||||||
0x0033 | // InvertRect
|
0x0007 | // PnSize
|
||||||
0x0034 => p += 8, // FillRect
|
0x000b | // OvSize
|
||||||
0x002d => p += 10, // LineJustify
|
0x000c | // Origin
|
||||||
0x0c00 => p += 24, // HeaderOp
|
0x000e | // FgCol
|
||||||
0x0001 => p += (b.c_u16b(p )? & !1) as usize, // Clip
|
0x000f | // BkCol
|
||||||
0x00a1 => p += (b.c_u16b(p+2)? & !1) as usize + 2, // LongComment
|
0x0021 => p += 4, // LineFrom
|
||||||
0x100..=
|
0x001a | // RGBFgCol
|
||||||
0x7fff => p += (op >> 8) as usize * 2, // Reserved
|
0x001b | // RGBBkCol
|
||||||
_ => return Err(err_msg("invalid op in PICT"))
|
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 {
|
for i in 0..num {
|
||||||
// with device mapping, we ignore the index entirely
|
// with device mapping, we ignore the index entirely
|
||||||
let n = if !dev {b[p+1] as usize} else {i};
|
let n = if !dev {b[p + 1] as usize} else {i};
|
||||||
let r = b[p+2];
|
let r = b[p + 2];
|
||||||
let g = b[p+4];
|
let g = b[p + 4];
|
||||||
let b = b[p+6];
|
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};
|
clut[n] = Color{r, g, b, a: 255};
|
||||||
|
|
||||||
p += 8;
|
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 p = 0;
|
||||||
let mut o = Vec::with_capacity(pitch);
|
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 {
|
while p < sz {
|
||||||
let szf = b[(p, p += 1).0];
|
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))}
|
if o.len() == pitch {
|
||||||
else {Err(err_msg("incorrect size for compressed scanline"))}
|
Ok((o, p))
|
||||||
|
} else {
|
||||||
|
Err(err_msg("incorrect size for compressed scanline"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a sequence of packed RLE data.
|
/// 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 {
|
if cmp {
|
||||||
let d = read();
|
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 {
|
} 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.
|
/// Expand packed pixel data based on bit depth.
|
||||||
pub fn expand_data(b: Vec<u8>, depth: u16) -> ResultS<Vec<u8>>
|
pub fn expand_data(b: Vec<u8>, depth: u16) -> ResultS<Vec<u8>>
|
||||||
{
|
{
|
||||||
let mut o = Vec::with_capacity(match depth {
|
let mut o =
|
||||||
4 => b.len() * 2,
|
Vec::with_capacity(match depth {
|
||||||
2 => b.len() * 4,
|
4 => b.len() * 2,
|
||||||
1 => b.len() * 8,
|
2 => b.len() * 4,
|
||||||
_ => return Err(err_msg("invalid bit depth"))
|
1 => b.len() * 8,
|
||||||
});
|
_ => return Err(err_msg("invalid bit depth")),
|
||||||
|
});
|
||||||
|
|
||||||
for ch in b {
|
for ch in b {
|
||||||
match depth {
|
match depth {
|
||||||
4 => for i in 1..=0 {o.push(ch >> i * 4 & 0xFu8);}, // 2 nibbles
|
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
|
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
|
1 => {for i in 7..=0 {o.push(ch >> i * 1 & 0x1u8);}} // 8 bits
|
||||||
_ => return Err(err_msg("invalid bit depth"))
|
_ => return Err(err_msg("invalid bit depth")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,12 @@ use std::fmt;
|
||||||
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
|
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
|
||||||
{
|
{
|
||||||
// flags = b.c_u16b( 0)?;
|
// flags = b.c_u16b( 0)?;
|
||||||
let ttype = b.c_u16b( 2)?;
|
let ttype = b.c_u16b(2)?;
|
||||||
let pdata = b.c_i16b( 4)?;
|
let pdata = b.c_i16b(4)?;
|
||||||
let start = b.c_u16b( 6)? as usize;
|
let start = b.c_u16b(6)? as usize;
|
||||||
let size = b.c_u16b( 8)? as usize;
|
let size = b.c_u16b(8)? as usize;
|
||||||
let lines = b.c_u16b(10)?;
|
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)?;
|
let ttype = GroupType::from_repr(ttype)?;
|
||||||
|
|
||||||
Ok(Group{ttype, pdata, lines, text})
|
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>
|
fn read_face(b: &[u8]) -> ResultS<Face>
|
||||||
{
|
{
|
||||||
let start = b.c_u16b(0)? as usize;
|
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)?;
|
let color = b.c_u16b(4)?;
|
||||||
|
|
||||||
Ok(Face{start, face, color})
|
Ok(Face { start, face, color })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
|
fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
|
||||||
{
|
{
|
||||||
const SIZE_GROUP: usize = 12;
|
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 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 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 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 mut p = 10; // size of header
|
||||||
|
|
||||||
let text_st = p + SIZE_GROUP * group_n + SIZE_FACE * face_n;
|
let text_st = p + SIZE_GROUP * group_n + SIZE_FACE * face_n;
|
||||||
let text = &b[text_st..end];
|
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 {
|
for _ in 0..group_n {
|
||||||
groups.push(read_group(&b[p..], &text)?);
|
groups.push(read_group(&b[p..], &text)?);
|
||||||
|
@ -77,16 +81,16 @@ impl Chunker<Vec<Terminal>> for Terminal
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Terminal
|
pub struct Terminal
|
||||||
{
|
{
|
||||||
lines: u16,
|
lines: u16,
|
||||||
groups: Vec<Group>,
|
groups: Vec<Group>,
|
||||||
faces: Vec<Face>,
|
faces: Vec<Face>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Face
|
pub struct Face
|
||||||
{
|
{
|
||||||
start: usize,
|
start: usize,
|
||||||
face: u16,
|
face: u16,
|
||||||
color: u16,
|
color: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +99,7 @@ pub struct Group
|
||||||
ttype: GroupType,
|
ttype: GroupType,
|
||||||
pdata: i16,
|
pdata: i16,
|
||||||
lines: u16,
|
lines: u16,
|
||||||
text: String,
|
text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
|
@ -127,7 +131,9 @@ impl fmt::Debug for Group
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
||||||
{
|
{
|
||||||
write!(f, "Group{{{:?} {} {}", self.ttype, self.pdata, self.lines)?;
|
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, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,39 +7,51 @@ impl Wad<'_>
|
||||||
{
|
{
|
||||||
pub fn new(b: &[u8]) -> ResultS<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 wadver = b.c_u16b(0)?;
|
||||||
let dataver = b.c_u16b( 2)?;
|
let dataver = b.c_u16b(2)?;
|
||||||
let origname = mac_roman_conv(&b[4..68]);
|
let origname = mac_roman_conv(&b[4..68]);
|
||||||
// crc = b.c_u32b(68)?;
|
// crc = b.c_u32b(68)?;
|
||||||
let dirofs = b.c_u32b(72)? as usize;
|
let dirofs = b.c_u32b(72)? as usize;
|
||||||
let numents = b.c_u16b(76)? as usize;
|
let numents = b.c_u16b(76)? as usize;
|
||||||
let appsize = b.c_u16b(78)? as usize;
|
let appsize = b.c_u16b(78)? as usize;
|
||||||
let wcnksize = b.c_u16b(80)? as usize;
|
let wcnksize = b.c_u16b(80)? as usize;
|
||||||
let wentsize = b.c_u16b(82)? as usize;
|
let wentsize = b.c_u16b(82)? as usize;
|
||||||
// parent = b.c_u32b(84)?;
|
// parent = b.c_u32b(84)?;
|
||||||
let wadver = Ver::from_repr(wadver)?;
|
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 entsize = if !is_old {10} else {8 };
|
||||||
let cnksize = if !is_old {16} else {12};
|
let cnksize = if !is_old {16} else {12};
|
||||||
|
|
||||||
if entsize != wentsize {return Err(err_msg("invalid entry size"));}
|
if entsize != wentsize {
|
||||||
if cnksize != wcnksize {return Err(err_msg("invalid chunk size"));}
|
return Err(err_msg("invalid entry size"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if cnksize != wcnksize {
|
||||||
|
return Err(err_msg("invalid chunk size"));
|
||||||
|
}
|
||||||
|
|
||||||
let mut entries = EntryMap::new();
|
let mut entries = EntryMap::new();
|
||||||
let mut p = dirofs;
|
let mut p = dirofs;
|
||||||
|
|
||||||
for i in 0..numents {
|
for i in 0..numents {
|
||||||
let offset = b.c_u32b(p )? as usize;
|
let offset = b.c_u32b(p)? as usize;
|
||||||
let size = b.c_u32b(p+4)? 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 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 chunks = get_chunks(&b[offset..offset + size], cnksize)?;
|
||||||
let appdata = &b[p..p+appsize];
|
let appdata = &b[p..p + appsize];
|
||||||
|
|
||||||
entries.insert(index, Entry{chunks, appdata});
|
entries.insert(index, Entry{chunks, appdata});
|
||||||
|
|
||||||
|
@ -56,12 +68,12 @@ fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
|
||||||
let mut p = 0;
|
let mut p = 0;
|
||||||
|
|
||||||
while p < b.len() {
|
while p < b.len() {
|
||||||
let iden = b.c_iden(p )?;
|
let iden = b.c_iden(p)?;
|
||||||
// ofs = b.c_u32b(p+ 4)?;
|
// 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)?;
|
// pofs = b.c_u32b(p+12)?;
|
||||||
let beg = p + cnksize;
|
let beg = p + cnksize;
|
||||||
let end = beg + size;
|
let end = beg + size;
|
||||||
chunks.insert(iden, &b[beg..end]);
|
chunks.insert(iden, &b[beg..end]);
|
||||||
p = end;
|
p = end;
|
||||||
}
|
}
|
||||||
|
@ -69,24 +81,24 @@ fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
|
||||||
Ok(chunks)
|
Ok(chunks)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Chunk <'a> = &'a[u8];
|
type Chunk<'a> = &'a [u8];
|
||||||
type ChunkMap<'a> = BTreeMap<Ident, Chunk<'a>>;
|
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 struct Entry<'a>
|
||||||
{
|
{
|
||||||
pub chunks: ChunkMap<'a>,
|
pub chunks: ChunkMap<'a>,
|
||||||
pub appdata: &'a[u8],
|
pub appdata: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Wad<'a>
|
pub struct Wad<'a>
|
||||||
{
|
{
|
||||||
wadver: Ver,
|
wadver: Ver,
|
||||||
dataver: u16,
|
dataver: u16,
|
||||||
origname: String,
|
origname: String,
|
||||||
appsize: usize,
|
appsize: usize,
|
||||||
pub entries: EntryMap<'a>,
|
pub entries: EntryMap<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
c_enum! {
|
c_enum! {
|
||||||
|
@ -105,8 +117,12 @@ impl fmt::Debug for Entry<'_>
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
||||||
{
|
{
|
||||||
write!(f, "Entry{{ ")?;
|
write!(f, "Entry{{ ")?;
|
||||||
for (iden, _) in &self.chunks {write!(f, "{} ", mac_roman_conv(iden))?;}
|
for (iden, _) in &self.chunks {
|
||||||
if self.appdata.len() != 0 {write!(f, "\nappdata: {:?} ", self.appdata)?;}
|
write!(f, "{} ", mac_roman_conv(iden))?;
|
||||||
|
}
|
||||||
|
if self.appdata.len() != 0 {
|
||||||
|
write!(f, "\nappdata: {:?} ", self.appdata)?;
|
||||||
|
}
|
||||||
write!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use maraiah::durandal::image::Color;
|
use maraiah::{durandal::image::Color, marathon::pict::get_clut};
|
||||||
use maraiah::marathon::pict::get_clut;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_clut_must_process_this()
|
fn get_clut_must_process_this()
|
||||||
|
|
|
@ -5,7 +5,7 @@ use maraiah::marathon::machdr::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn macbin_must_process_this()
|
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);
|
assert_eq!(try_mac_header(INPUT_MACBIN), 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue