Maraiah/src/marathon/term.rs

170 lines
3.4 KiB
Rust
Raw Normal View History

2018-09-11 01:21:36 -07:00
use std::fmt;
2018-12-08 14:54:42 -08:00
use crate::durandal::text::*;
use crate::durandal::bin::*;
2018-09-11 01:21:36 -07:00
impl Terminal
{
2018-09-11 12:07:42 -07:00
pub fn read(b: &[u8]) -> ResultS<(usize, Terminal)>
2018-09-11 01:21:36 -07:00
{
const SIZE_HEAD : usize = 10;
const SIZE_GROUP: usize = 12;
const SIZE_FACE : usize = 6;
2018-09-11 12:07:42 -07:00
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;
2018-09-11 01:21:36 -07:00
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
{
2018-09-11 12:07:42 -07:00
// 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)?;
2018-09-11 01:21:36 -07:00
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)};
2018-09-11 01:21:36 -07:00
grp.push(Group{typ, per, lns, txt});
p += SIZE_GROUP;
}
for _ in 0..fnu
{
2018-09-11 12:07:42 -07:00
let ind = b.c_u16b(p )?;
let fce = b.c_u16b(p+2)?;
let col = b.c_u16b(p+4)?;
2018-09-11 01:21:36 -07:00
fcs.push(Face{ind, fce, col});
p += SIZE_FACE;
}
Ok((len, Terminal{enc, lns, grp, fcs}))
2018-09-11 01:21:36 -07:00
}
2018-09-11 12:07:42 -07:00
pub fn chunk(b: &[u8]) -> ResultS<Vec<Terminal>>
2018-09-11 01:21:36 -07:00
{
let mut v = Vec::new();
let mut p = 0;
while p < b.len()
{
let sta = p;
2018-09-11 12:07:42 -07:00
let (len, trm) = Terminal::read(&b[p..])?;
2018-09-11 01:21:36 -07:00
v.push(trm);
p = sta + len;
}
2018-09-11 12:07:42 -07:00
Ok(v)
2018-09-11 01:21:36 -07:00
}
}
#[derive(Debug)]
pub struct Terminal
{
enc: bool,
2018-09-11 01:21:36 -07:00
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)?;
2018-09-11 12:07:42 -07:00
if self.txt.len() != 0 {write!(f, ";\n{}\n", self.txt)?}
2018-09-11 01:21:36 -07:00
write!(f, "}}")
}
}
// EOF