normalize line endings

png-branch
an 2019-02-09 00:08:53 -05:00
parent 69063cc41a
commit dd5bf03252
4 changed files with 286 additions and 286 deletions

View File

@ -1,28 +1,28 @@
//! Cyclic redundancy check function. //! Cyclic redundancy check function.
fn crc_accum(a: u32) -> u32 fn crc_accum(a: u32) -> u32
{ {
if a & 1 == 1 {0xedb88320 ^ a >> 1} if a & 1 == 1 {0xedb88320 ^ a >> 1}
else {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]
fn crc32_lorem_ipsum() fn crc32_lorem_ipsum()
{ {
assert_eq!(crc32(b"Lorem ipsum dolor sit amet", !0), 0x5F29D461); assert_eq!(crc32(b"Lorem ipsum dolor sit amet", !0), 0x5F29D461);
} }
// EOF // EOF

View File

@ -1,9 +1,9 @@
//! Library for file data formats. //! Library for file data formats.
pub mod machdr; pub mod machdr;
pub mod map; pub mod map;
pub mod pict; pub mod pict;
pub mod term; pub mod term;
pub mod wad; pub mod wad;
// EOF // EOF

View File

@ -1,135 +1,135 @@
use crate::durandal::{bin::*, chunk::*, err::*, text::*}; use crate::durandal::{bin::*, chunk::*, err::*, text::*};
use std::fmt; 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})
} }
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)?);
p += SIZE_GROUP; p += SIZE_GROUP;
} }
for _ in 0..face_n { for _ in 0..face_n {
faces.push(read_face(&b[p..])?); faces.push(read_face(&b[p..])?);
p += SIZE_FACE; p += SIZE_FACE;
} }
Ok((end, Terminal{lines, groups, faces})) Ok((end, Terminal{lines, groups, faces}))
} }
impl Chunker<Vec<Terminal>> for Terminal impl Chunker<Vec<Terminal>> for Terminal
{ {
fn chunk(b: &[u8]) -> ResultS<Vec<Terminal>> fn chunk(b: &[u8]) -> ResultS<Vec<Terminal>>
{ {
let mut v = Vec::new(); let mut v = Vec::new();
let mut p = 0; let mut p = 0;
while p < b.len() { while p < b.len() {
let (size, trm) = read_terminal(&b[p..])?; let (size, trm) = read_terminal(&b[p..])?;
v.push(trm); v.push(trm);
p += size; p += size;
} }
Ok(v) Ok(v)
} }
} }
#[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,
} }
pub struct Group pub struct Group
{ {
ttype: GroupType, ttype: GroupType,
pdata: i16, pdata: i16,
lines: u16, lines: u16,
text: String, text: String,
} }
c_enum! { c_enum! {
#[derive(Debug)] #[derive(Debug)]
pub enum GroupType: u16 pub enum GroupType: u16
{ {
0 => Logon, 0 => Logon,
1 => Unfinished, 1 => Unfinished,
2 => Success, 2 => Success,
3 => Failure, 3 => Failure,
4 => Info, 4 => Info,
5 => End, 5 => End,
6 => TeleInter, 6 => TeleInter,
7 => TeleIntra, 7 => TeleIntra,
8 => Checkpoint, 8 => Checkpoint,
9 => Sound, 9 => Sound,
10 => Movie, 10 => Movie,
11 => Track, 11 => Track,
12 => Pict, 12 => Pict,
13 => Logoff, 13 => Logoff,
14 => Camera, 14 => Camera,
15 => Static, 15 => Static,
16 => Tag, 16 => Tag,
} }
} }
impl fmt::Debug for Group 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, "}}")
} }
} }
// EOF // EOF

View File

@ -1,114 +1,114 @@
//! Marathon Wad format handling. //! Marathon Wad format handling.
use crate::durandal::{bin::*, err::*, text::mac_roman_conv}; use crate::durandal::{bin::*, err::*, text::mac_roman_conv};
use std::{collections::BTreeMap, fmt}; use std::{collections::BTreeMap, fmt};
impl Wad<'_> 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 {return Err(err_msg("invalid entry size"));}
if cnksize != wcnksize {return Err(err_msg("invalid chunk 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});
p += entsize + appsize; p += entsize + appsize;
} }
Ok(Wad{wadver, dataver, appsize, origname, entries}) Ok(Wad{wadver, dataver, appsize, origname, entries})
} }
} }
fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap> fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
{ {
let mut chunks = ChunkMap::new(); let mut chunks = ChunkMap::new();
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;
} }
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! {
#[derive(Debug)] #[derive(Debug)]
pub enum Ver: u16 pub enum Ver: u16
{ {
0 => Base, 0 => Base,
1 => Dir, 1 => Dir,
2 => Over, 2 => Over,
4 => Inf, 4 => Inf,
} }
} }
impl fmt::Debug for Entry<'_> 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 {write!(f, "{} ", mac_roman_conv(iden))?;}
if self.appdata.len() != 0 {write!(f, "\nappdata: {:?} ", self.appdata)?;} if self.appdata.len() != 0 {write!(f, "\nappdata: {:?} ", self.appdata)?;}
write!(f, "}}") write!(f, "}}")
} }
} }
// EOF // EOF