add C repr stuff
parent
a3e9dde0ff
commit
c1ece8b116
|
@ -8,4 +8,5 @@ edition = "2018"
|
||||||
memmap = "0.6"
|
memmap = "0.6"
|
||||||
generic-array = "0.12"
|
generic-array = "0.12"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
|
bitflags = "1.0"
|
||||||
#gtk = "0.4"
|
#gtk = "0.4"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Library for file reading utilities and mac format utilities.
|
//! Library for various utilities.
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub mod bin;
|
pub mod bin;
|
||||||
|
@ -10,4 +10,36 @@ pub mod machead;
|
||||||
pub mod pict;
|
pub mod pict;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
|
/// Creates an enumeration and function for converting a representation into
|
||||||
|
/// the enumeration type.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! c_enum
|
||||||
|
{
|
||||||
|
(
|
||||||
|
$(#[$outer:meta])*
|
||||||
|
pub enum $E:ident: $T:ty
|
||||||
|
{
|
||||||
|
$($value:expr => $Enum:ident,)+
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
$(#[$outer])*
|
||||||
|
pub enum $E
|
||||||
|
{
|
||||||
|
$($Enum,)+
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $E
|
||||||
|
{
|
||||||
|
pub fn from_repr(n: $T) -> ResultS<$E>
|
||||||
|
{
|
||||||
|
let t = match n {
|
||||||
|
$($value => $E::$Enum,)+
|
||||||
|
n => return Err(format_err!("invalid representation for {} (got {})", stringify!($E), n))
|
||||||
|
};
|
||||||
|
Ok(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
use crate::durandal::{bin::*, err::*, text::*};
|
use crate::durandal::{bin::*, err::*, text::*};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub 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)?.into();
|
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)?;
|
||||||
|
|
||||||
Ok(Group{ttype, pdata, lines, text})
|
Ok(Group{ttype, pdata, lines, text})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub 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)?;
|
||||||
|
@ -23,7 +24,7 @@ pub fn read_face(b: &[u8]) -> ResultS<Face>
|
||||||
Ok(Face{start, face, color})
|
Ok(Face{start, face, color})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub 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;
|
||||||
|
@ -81,6 +82,7 @@ pub struct Terminal
|
||||||
faces: Vec<Face>,
|
faces: Vec<Face>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Face
|
pub struct Face
|
||||||
{
|
{
|
||||||
start: usize,
|
start: usize,
|
||||||
|
@ -90,66 +92,33 @@ pub struct Face
|
||||||
|
|
||||||
pub struct Group
|
pub struct Group
|
||||||
{
|
{
|
||||||
ttype: Type,
|
ttype: GroupType,
|
||||||
pdata: i16,
|
pdata: i16,
|
||||||
lines: u16,
|
lines: u16,
|
||||||
text: String,
|
text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
c_enum! {
|
||||||
pub enum Type
|
#[derive(Debug)]
|
||||||
{
|
pub enum GroupType: u16
|
||||||
Logon,
|
|
||||||
Unfinished,
|
|
||||||
Success,
|
|
||||||
Failure,
|
|
||||||
Info,
|
|
||||||
End,
|
|
||||||
TeleInter,
|
|
||||||
TeleIntra,
|
|
||||||
Checkpoint,
|
|
||||||
Sound,
|
|
||||||
Movie,
|
|
||||||
Track,
|
|
||||||
Pict,
|
|
||||||
Logoff,
|
|
||||||
Camera,
|
|
||||||
Static,
|
|
||||||
Tag,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<u16> for Type
|
|
||||||
{
|
|
||||||
fn from(n: u16) -> Self
|
|
||||||
{
|
{
|
||||||
match n {
|
0 => Logon,
|
||||||
0 => Type::Logon,
|
1 => Unfinished,
|
||||||
1 => Type::Unfinished,
|
2 => Success,
|
||||||
2 => Type::Success,
|
3 => Failure,
|
||||||
3 => Type::Failure,
|
4 => Info,
|
||||||
4 => Type::Info,
|
5 => End,
|
||||||
5 => Type::End,
|
6 => TeleInter,
|
||||||
6 => Type::TeleInter,
|
7 => TeleIntra,
|
||||||
7 => Type::TeleIntra,
|
8 => Checkpoint,
|
||||||
8 => Type::Checkpoint,
|
9 => Sound,
|
||||||
9 => Type::Sound,
|
10 => Movie,
|
||||||
10 => Type::Movie,
|
11 => Track,
|
||||||
11 => Type::Track,
|
12 => Pict,
|
||||||
12 => Type::Pict,
|
13 => Logoff,
|
||||||
13 => Type::Logoff,
|
14 => Camera,
|
||||||
14 => Type::Camera,
|
15 => Static,
|
||||||
15 => Type::Static,
|
16 => Tag,
|
||||||
16 => Type::Tag,
|
|
||||||
_ => panic!("invalid terminal group type {}", n),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Face
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
|
||||||
{
|
|
||||||
write!(f, "Face{{{} {} {}}}", self.start, self.face, self.color)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +127,7 @@ 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{}\n", self.text)?;}
|
if self.text.len() != 0 {write!(f, ";\n{}", self.text)?;}
|
||||||
write!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,45 +3,6 @@
|
||||||
use crate::durandal::{bin::*, err::*, machead::try_mac_header, text::mac_roman_conv};
|
use crate::durandal::{bin::*, err::*, machead::try_mac_header, text::mac_roman_conv};
|
||||||
use std::{collections::BTreeMap, fmt};
|
use std::{collections::BTreeMap, fmt};
|
||||||
|
|
||||||
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>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Ver
|
|
||||||
{
|
|
||||||
Base,
|
|
||||||
Dir,
|
|
||||||
Over,
|
|
||||||
MI
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Entry<'_>
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
|
||||||
{
|
|
||||||
write!(f, "Entry{{ ")?;
|
|
||||||
for (ident, _) in &self.chunks {write!(f, "{} ", mac_roman_conv(ident))?;}
|
|
||||||
write!(f, "}}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Wad<'_>
|
impl Wad<'_>
|
||||||
{
|
{
|
||||||
pub fn new(b: &[u8]) -> ResultS<Wad>
|
pub fn new(b: &[u8]) -> ResultS<Wad>
|
||||||
|
@ -60,14 +21,7 @@ impl Wad<'_>
|
||||||
// entsize = b.c_u16b(82)?;
|
// entsize = b.c_u16b(82)?;
|
||||||
// parent = b.c_u32b(84)?;
|
// parent = b.c_u32b(84)?;
|
||||||
|
|
||||||
let wadver = match wadver {
|
let wadver = Ver::from_repr(wadver)?;
|
||||||
4 => Ver::MI,
|
|
||||||
2 => Ver::Over,
|
|
||||||
1 => Ver::Dir,
|
|
||||||
0 => Ver::Base,
|
|
||||||
_ => return err_msg("invalid Wad version"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let is_old = match wadver {Ver::Base => true, _ => false};
|
let is_old = match wadver {Ver::Base => true, _ => false};
|
||||||
let entsize = if is_old {8} else {10};
|
let entsize = if is_old {8} else {10};
|
||||||
|
|
||||||
|
@ -79,7 +33,7 @@ impl Wad<'_>
|
||||||
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_msg("not enough data for entry")}
|
if offset + size > b.len() {return err_msg("not enough data for entry");}
|
||||||
|
|
||||||
let chunks = get_chunks(&b[offset..offset+size], is_old)?;
|
let chunks = get_chunks(&b[offset..offset+size], is_old)?;
|
||||||
let appdata = &b[p+entsize..p+entsize+appsize];
|
let appdata = &b[p+entsize..p+entsize+appsize];
|
||||||
|
@ -114,4 +68,46 @@ fn get_chunks(b: &[u8], is_old: bool) -> ResultS<ChunkMap>
|
||||||
Ok(chunks)
|
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 => MI,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Entry<'_>
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
||||||
|
{
|
||||||
|
write!(f, "Entry{{ ")?;
|
||||||
|
for (ident, _) in &self.chunks {write!(f, "{} ", mac_roman_conv(ident))?;}
|
||||||
|
if self.appdata.len() != 0{write!(f, "\nappdata: {:?} ", self.appdata)?;}
|
||||||
|
write!(f, "}}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
Loading…
Reference in New Issue