165 lines
3.3 KiB
Rust
165 lines
3.3 KiB
Rust
use crate::durandal::{bin::*, err::*, text::*};
|
|
use std::fmt;
|
|
|
|
impl Terminal
|
|
{
|
|
pub fn read(b: &[u8]) -> ResultS<(usize, Terminal)>
|
|
{
|
|
const SIZE_HEAD : usize = 10;
|
|
const SIZE_GROUP: usize = 12;
|
|
const SIZE_FACE : usize = 6;
|
|
|
|
let len = b.c_u16b(0)? as usize;
|
|
let enc = b.c_u16b(2)? & 1 != 0;
|
|
let lns = b.c_u16b(4)?;
|
|
let gnu = b.c_u16b(6)? as usize;
|
|
let fnu = b.c_u16b(8)? as usize;
|
|
|
|
let mut grp = Vec::with_capacity(gnu);
|
|
let mut fcs = Vec::with_capacity(fnu);
|
|
let end = SIZE_GROUP * gnu + SIZE_FACE * fnu + SIZE_HEAD;
|
|
|
|
let mut p = SIZE_HEAD;
|
|
|
|
for _ in 0..gnu {
|
|
// flg = b.c_u16b(p )?;
|
|
let typ = b.c_u16b(p+ 2)?.into();
|
|
let per = b.c_i16b(p+ 4)?;
|
|
let beg = b.c_u16b(p+ 6)? as usize;
|
|
let len = b.c_u16b(p+ 8)? as usize;
|
|
let lns = b.c_u16b(p+10)?;
|
|
|
|
let sta = end + beg;
|
|
|
|
let txt = &b[sta..sta+len];
|
|
let txt = if enc {mac_roman_conv(&fuck_string(txt))}
|
|
else {mac_roman_conv(&txt)};
|
|
|
|
grp.push(Group{typ, per, lns, txt});
|
|
|
|
p += SIZE_GROUP;
|
|
}
|
|
|
|
for _ in 0..fnu {
|
|
let ind = b.c_u16b(p )?;
|
|
let fce = b.c_u16b(p+2)?;
|
|
let col = b.c_u16b(p+4)?;
|
|
|
|
fcs.push(Face{ind, fce, col});
|
|
|
|
p += SIZE_FACE;
|
|
}
|
|
|
|
Ok((len, Terminal{enc, lns, grp, fcs}))
|
|
}
|
|
|
|
pub fn chunk(b: &[u8]) -> ResultS<Vec<Terminal>>
|
|
{
|
|
let mut v = Vec::new();
|
|
let mut p = 0;
|
|
|
|
while p < b.len() {
|
|
let sta = p;
|
|
|
|
let (len, trm) = Terminal::read(&b[p..])?;
|
|
|
|
v.push(trm);
|
|
|
|
p = sta + len;
|
|
}
|
|
|
|
Ok(v)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Terminal
|
|
{
|
|
enc: bool,
|
|
lns: u16,
|
|
grp: Vec<Group>,
|
|
fcs: Vec<Face>,
|
|
}
|
|
|
|
pub struct Face
|
|
{
|
|
ind: u16,
|
|
fce: u16,
|
|
col: u16,
|
|
}
|
|
|
|
pub struct Group
|
|
{
|
|
typ: Type,
|
|
per: i16,
|
|
lns: u16,
|
|
txt: String,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum Type
|
|
{
|
|
Logon,
|
|
Unfinished,
|
|
Success,
|
|
Failure,
|
|
Information,
|
|
End,
|
|
InterlevelTeleport,
|
|
IntralevelTeleport,
|
|
Checkpoint,
|
|
Sound,
|
|
Movie,
|
|
Track,
|
|
Pict,
|
|
Logoff,
|
|
Camera,
|
|
Static,
|
|
TagActivate,
|
|
}
|
|
|
|
impl From<u16> for Type
|
|
{
|
|
fn from(n: u16) -> Self
|
|
{
|
|
match n {
|
|
0 => Type::Logon,
|
|
1 => Type::Unfinished,
|
|
2 => Type::Success,
|
|
3 => Type::Failure,
|
|
4 => Type::Information,
|
|
5 => Type::End,
|
|
6 => Type::InterlevelTeleport,
|
|
7 => Type::IntralevelTeleport,
|
|
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::TagActivate,
|
|
_ => panic!("invalid terminal group type {}", n),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Debug for Face
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
|
{write!(f, "Face{{{} {} {}}}", self.ind, self.fce, self.col)}
|
|
}
|
|
|
|
impl fmt::Debug for Group
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
|
{
|
|
write!(f, "Group{{{:?} {} {}", self.typ, self.per, self.lns)?;
|
|
if self.txt.len() != 0 {write!(f, ";\n{}\n", self.txt)?}
|
|
write!(f, "}}")
|
|
}
|
|
}
|
|
|
|
// EOF
|