normalize line endings
parent
69063cc41a
commit
dd5bf03252
|
@ -1,28 +1,28 @@
|
|||
//! Cyclic redundancy check function.
|
||||
|
||||
fn crc_accum(a: u32) -> u32
|
||||
{
|
||||
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));}
|
||||
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]})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crc32_lorem_ipsum()
|
||||
{
|
||||
assert_eq!(crc32(b"Lorem ipsum dolor sit amet", !0), 0x5F29D461);
|
||||
}
|
||||
|
||||
// EOF
|
||||
//! Cyclic redundancy check function.
|
||||
|
||||
fn crc_accum(a: u32) -> u32
|
||||
{
|
||||
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));}
|
||||
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]})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crc32_lorem_ipsum()
|
||||
{
|
||||
assert_eq!(crc32(b"Lorem ipsum dolor sit amet", !0), 0x5F29D461);
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//! Library for file data formats.
|
||||
|
||||
pub mod machdr;
|
||||
pub mod map;
|
||||
pub mod pict;
|
||||
pub mod term;
|
||||
pub mod wad;
|
||||
|
||||
// EOF
|
||||
//! Library for file data formats.
|
||||
|
||||
pub mod machdr;
|
||||
pub mod map;
|
||||
pub mod pict;
|
||||
pub mod term;
|
||||
pub mod wad;
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -1,135 +1,135 @@
|
|||
use crate::durandal::{bin::*, chunk::*, err::*, text::*};
|
||||
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 lines = b.c_u16b(10)?;
|
||||
let text = mac_roman_conv(&text[start..start+size]);
|
||||
let ttype = GroupType::from_repr(ttype)?;
|
||||
|
||||
Ok(Group{ttype, pdata, lines, text})
|
||||
}
|
||||
|
||||
fn read_face(b: &[u8]) -> ResultS<Face>
|
||||
{
|
||||
let start = b.c_u16b(0)? as usize;
|
||||
let face = b.c_u16b(2)?;
|
||||
let color = b.c_u16b(4)?;
|
||||
|
||||
Ok(Face{start, face, color})
|
||||
}
|
||||
|
||||
fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
|
||||
{
|
||||
const SIZE_GROUP: usize = 12;
|
||||
const SIZE_FACE : usize = 6;
|
||||
|
||||
let end = b.c_u16b(0)? as usize;
|
||||
let encoded = b.c_u16b(2)? & 1 != 0;
|
||||
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 mut groups = Vec::with_capacity(group_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()};
|
||||
|
||||
for _ in 0..group_n {
|
||||
groups.push(read_group(&b[p..], &text)?);
|
||||
p += SIZE_GROUP;
|
||||
}
|
||||
|
||||
for _ in 0..face_n {
|
||||
faces.push(read_face(&b[p..])?);
|
||||
p += SIZE_FACE;
|
||||
}
|
||||
|
||||
Ok((end, Terminal{lines, groups, faces}))
|
||||
}
|
||||
|
||||
impl Chunker<Vec<Terminal>> for Terminal
|
||||
{
|
||||
fn chunk(b: &[u8]) -> ResultS<Vec<Terminal>>
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
let mut p = 0;
|
||||
|
||||
while p < b.len() {
|
||||
let (size, trm) = read_terminal(&b[p..])?;
|
||||
v.push(trm);
|
||||
p += size;
|
||||
}
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Terminal
|
||||
{
|
||||
lines: u16,
|
||||
groups: Vec<Group>,
|
||||
faces: Vec<Face>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Face
|
||||
{
|
||||
start: usize,
|
||||
face: u16,
|
||||
color: u16,
|
||||
}
|
||||
|
||||
pub struct Group
|
||||
{
|
||||
ttype: GroupType,
|
||||
pdata: i16,
|
||||
lines: u16,
|
||||
text: String,
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
#[derive(Debug)]
|
||||
pub enum GroupType: u16
|
||||
{
|
||||
0 => Logon,
|
||||
1 => Unfinished,
|
||||
2 => Success,
|
||||
3 => Failure,
|
||||
4 => Info,
|
||||
5 => End,
|
||||
6 => TeleInter,
|
||||
7 => TeleIntra,
|
||||
8 => Checkpoint,
|
||||
9 => Sound,
|
||||
10 => Movie,
|
||||
11 => Track,
|
||||
12 => Pict,
|
||||
13 => Logoff,
|
||||
14 => Camera,
|
||||
15 => Static,
|
||||
16 => Tag,
|
||||
}
|
||||
}
|
||||
|
||||
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)?;}
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
||||
use crate::durandal::{bin::*, chunk::*, err::*, text::*};
|
||||
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 lines = b.c_u16b(10)?;
|
||||
let text = mac_roman_conv(&text[start..start+size]);
|
||||
let ttype = GroupType::from_repr(ttype)?;
|
||||
|
||||
Ok(Group{ttype, pdata, lines, text})
|
||||
}
|
||||
|
||||
fn read_face(b: &[u8]) -> ResultS<Face>
|
||||
{
|
||||
let start = b.c_u16b(0)? as usize;
|
||||
let face = b.c_u16b(2)?;
|
||||
let color = b.c_u16b(4)?;
|
||||
|
||||
Ok(Face{start, face, color})
|
||||
}
|
||||
|
||||
fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
|
||||
{
|
||||
const SIZE_GROUP: usize = 12;
|
||||
const SIZE_FACE : usize = 6;
|
||||
|
||||
let end = b.c_u16b(0)? as usize;
|
||||
let encoded = b.c_u16b(2)? & 1 != 0;
|
||||
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 mut groups = Vec::with_capacity(group_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()};
|
||||
|
||||
for _ in 0..group_n {
|
||||
groups.push(read_group(&b[p..], &text)?);
|
||||
p += SIZE_GROUP;
|
||||
}
|
||||
|
||||
for _ in 0..face_n {
|
||||
faces.push(read_face(&b[p..])?);
|
||||
p += SIZE_FACE;
|
||||
}
|
||||
|
||||
Ok((end, Terminal{lines, groups, faces}))
|
||||
}
|
||||
|
||||
impl Chunker<Vec<Terminal>> for Terminal
|
||||
{
|
||||
fn chunk(b: &[u8]) -> ResultS<Vec<Terminal>>
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
let mut p = 0;
|
||||
|
||||
while p < b.len() {
|
||||
let (size, trm) = read_terminal(&b[p..])?;
|
||||
v.push(trm);
|
||||
p += size;
|
||||
}
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Terminal
|
||||
{
|
||||
lines: u16,
|
||||
groups: Vec<Group>,
|
||||
faces: Vec<Face>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Face
|
||||
{
|
||||
start: usize,
|
||||
face: u16,
|
||||
color: u16,
|
||||
}
|
||||
|
||||
pub struct Group
|
||||
{
|
||||
ttype: GroupType,
|
||||
pdata: i16,
|
||||
lines: u16,
|
||||
text: String,
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
#[derive(Debug)]
|
||||
pub enum GroupType: u16
|
||||
{
|
||||
0 => Logon,
|
||||
1 => Unfinished,
|
||||
2 => Success,
|
||||
3 => Failure,
|
||||
4 => Info,
|
||||
5 => End,
|
||||
6 => TeleInter,
|
||||
7 => TeleIntra,
|
||||
8 => Checkpoint,
|
||||
9 => Sound,
|
||||
10 => Movie,
|
||||
11 => Track,
|
||||
12 => Pict,
|
||||
13 => Logoff,
|
||||
14 => Camera,
|
||||
15 => Static,
|
||||
16 => Tag,
|
||||
}
|
||||
}
|
||||
|
||||
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)?;}
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -1,114 +1,114 @@
|
|||
//! Marathon Wad format handling.
|
||||
|
||||
use crate::durandal::{bin::*, err::*, text::mac_roman_conv};
|
||||
use std::{collections::BTreeMap, fmt};
|
||||
|
||||
impl Wad<'_>
|
||||
{
|
||||
pub fn new(b: &[u8]) -> ResultS<Wad>
|
||||
{
|
||||
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 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;
|
||||
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)?;
|
||||
|
||||
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"));}
|
||||
|
||||
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};
|
||||
|
||||
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];
|
||||
|
||||
entries.insert(index, Entry{chunks, appdata});
|
||||
|
||||
p += entsize + appsize;
|
||||
}
|
||||
|
||||
Ok(Wad{wadver, dataver, appsize, origname, entries})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
|
||||
{
|
||||
let mut chunks = ChunkMap::new();
|
||||
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;
|
||||
// pofs = b.c_u32b(p+12)?;
|
||||
let beg = p + cnksize;
|
||||
let end = beg + size;
|
||||
chunks.insert(iden, &b[beg..end]);
|
||||
p = end;
|
||||
}
|
||||
|
||||
Ok(chunks)
|
||||
}
|
||||
|
||||
type Chunk <'a> = &'a[u8];
|
||||
type ChunkMap<'a> = BTreeMap<Ident, Chunk<'a>>;
|
||||
type EntryMap<'a> = BTreeMap<u16 , Entry<'a>>;
|
||||
|
||||
pub struct Entry<'a>
|
||||
{
|
||||
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>,
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
#[derive(Debug)]
|
||||
pub enum Ver: u16
|
||||
{
|
||||
0 => Base,
|
||||
1 => Dir,
|
||||
2 => Over,
|
||||
4 => Inf,
|
||||
}
|
||||
}
|
||||
|
||||
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)?;}
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
||||
//! Marathon Wad format handling.
|
||||
|
||||
use crate::durandal::{bin::*, err::*, text::mac_roman_conv};
|
||||
use std::{collections::BTreeMap, fmt};
|
||||
|
||||
impl Wad<'_>
|
||||
{
|
||||
pub fn new(b: &[u8]) -> ResultS<Wad>
|
||||
{
|
||||
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 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;
|
||||
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)?;
|
||||
|
||||
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"));}
|
||||
|
||||
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};
|
||||
|
||||
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];
|
||||
|
||||
entries.insert(index, Entry{chunks, appdata});
|
||||
|
||||
p += entsize + appsize;
|
||||
}
|
||||
|
||||
Ok(Wad{wadver, dataver, appsize, origname, entries})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_chunks(b: &[u8], cnksize: usize) -> ResultS<ChunkMap>
|
||||
{
|
||||
let mut chunks = ChunkMap::new();
|
||||
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;
|
||||
// pofs = b.c_u32b(p+12)?;
|
||||
let beg = p + cnksize;
|
||||
let end = beg + size;
|
||||
chunks.insert(iden, &b[beg..end]);
|
||||
p = end;
|
||||
}
|
||||
|
||||
Ok(chunks)
|
||||
}
|
||||
|
||||
type Chunk <'a> = &'a[u8];
|
||||
type ChunkMap<'a> = BTreeMap<Ident, Chunk<'a>>;
|
||||
type EntryMap<'a> = BTreeMap<u16 , Entry<'a>>;
|
||||
|
||||
pub struct Entry<'a>
|
||||
{
|
||||
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>,
|
||||
}
|
||||
|
||||
c_enum! {
|
||||
#[derive(Debug)]
|
||||
pub enum Ver: u16
|
||||
{
|
||||
0 => Base,
|
||||
1 => Dir,
|
||||
2 => Over,
|
||||
4 => Inf,
|
||||
}
|
||||
}
|
||||
|
||||
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)?;}
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
Loading…
Reference in New Issue