add C repr stuff
parent
a3e9dde0ff
commit
c1ece8b116
|
@ -8,4 +8,5 @@ edition = "2018"
|
|||
memmap = "0.6"
|
||||
generic-array = "0.12"
|
||||
failure = "0.1"
|
||||
bitflags = "1.0"
|
||||
#gtk = "0.4"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Library for file reading utilities and mac format utilities.
|
||||
//! Library for various utilities.
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub mod bin;
|
||||
|
@ -10,4 +10,36 @@ pub mod machead;
|
|||
pub mod pict;
|
||||
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
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
use crate::durandal::{bin::*, err::*, text::*};
|
||||
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)?;
|
||||
let ttype = b.c_u16b( 2)?.into();
|
||||
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})
|
||||
}
|
||||
|
||||
pub fn read_face(b: &[u8]) -> ResultS<Face>
|
||||
fn read_face(b: &[u8]) -> ResultS<Face>
|
||||
{
|
||||
let start = b.c_u16b(0)? as usize;
|
||||
let face = b.c_u16b(2)?;
|
||||
|
@ -23,7 +24,7 @@ pub fn read_face(b: &[u8]) -> ResultS<Face>
|
|||
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_FACE : usize = 6;
|
||||
|
@ -81,6 +82,7 @@ pub struct Terminal
|
|||
faces: Vec<Face>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Face
|
||||
{
|
||||
start: usize,
|
||||
|
@ -90,66 +92,33 @@ pub struct Face
|
|||
|
||||
pub struct Group
|
||||
{
|
||||
ttype: Type,
|
||||
ttype: GroupType,
|
||||
pdata: i16,
|
||||
lines: u16,
|
||||
text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Type
|
||||
{
|
||||
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
|
||||
c_enum! {
|
||||
#[derive(Debug)]
|
||||
pub enum GroupType: u16
|
||||
{
|
||||
match n {
|
||||
0 => Type::Logon,
|
||||
1 => Type::Unfinished,
|
||||
2 => Type::Success,
|
||||
3 => Type::Failure,
|
||||
4 => Type::Info,
|
||||
5 => Type::End,
|
||||
6 => Type::TeleInter,
|
||||
7 => Type::TeleIntra,
|
||||
8 => Type::Checkpoint,
|
||||
9 => Type::Sound,
|
||||
10 => Type::Movie,
|
||||
11 => Type::Track,
|
||||
12 => Type::Pict,
|
||||
13 => Type::Logoff,
|
||||
14 => Type::Camera,
|
||||
15 => Type::Static,
|
||||
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)
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +127,7 @@ 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{}\n", self.text)?;}
|
||||
if self.text.len() != 0 {write!(f, ";\n{}", self.text)?;}
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,45 +3,6 @@
|
|||
use crate::durandal::{bin::*, err::*, machead::try_mac_header, text::mac_roman_conv};
|
||||
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<'_>
|
||||
{
|
||||
pub fn new(b: &[u8]) -> ResultS<Wad>
|
||||
|
@ -60,14 +21,7 @@ impl Wad<'_>
|
|||
// entsize = b.c_u16b(82)?;
|
||||
// parent = b.c_u32b(84)?;
|
||||
|
||||
let wadver = match wadver {
|
||||
4 => Ver::MI,
|
||||
2 => Ver::Over,
|
||||
1 => Ver::Dir,
|
||||
0 => Ver::Base,
|
||||
_ => return err_msg("invalid Wad version"),
|
||||
};
|
||||
|
||||
let wadver = Ver::from_repr(wadver)?;
|
||||
let is_old = match wadver {Ver::Base => true, _ => false};
|
||||
let entsize = if is_old {8} else {10};
|
||||
|
||||
|
@ -79,7 +33,7 @@ impl Wad<'_>
|
|||
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_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 appdata = &b[p+entsize..p+entsize+appsize];
|
||||
|
@ -114,4 +68,46 @@ fn get_chunks(b: &[u8], is_old: bool) -> ResultS<ChunkMap>
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue