180 lines
4.2 KiB
Rust
180 lines
4.2 KiB
Rust
//! Structures used by Marathon's Map format's terminal definitions.
|
|
|
|
use crate::durandal::{bin::*, err::*, text::*};
|
|
use bitflags::bitflags;
|
|
|
|
/// Reads an `InterGroup`.
|
|
pub fn read_group(b: &[u8]) -> ResultS<(InterGroup, usize)>
|
|
{
|
|
read_data! {
|
|
endian: BIG, buf: b, size: 12, start: 0, data {
|
|
let flags = u16[0] flag GroupFlags;
|
|
let ttype = u16[2];
|
|
let pdata = u16[4];
|
|
let beg = u16[6] usize;
|
|
let len = u16[8] usize;
|
|
let lines = u16[10];
|
|
}
|
|
}
|
|
|
|
let ttype = match ttype {
|
|
0 => GroupType::Logon(pdata),
|
|
1 => GroupType::Unfinished,
|
|
2 => GroupType::Success,
|
|
3 => GroupType::Failure,
|
|
4 => GroupType::Info,
|
|
5 => GroupType::End,
|
|
6 => GroupType::TeleInter(pdata),
|
|
7 => GroupType::TeleIntra(pdata),
|
|
8 => GroupType::Checkpoint(pdata),
|
|
9 => GroupType::Sound(pdata),
|
|
10 => GroupType::Movie(pdata),
|
|
11 => GroupType::Track(pdata),
|
|
12 => GroupType::Pict(pdata),
|
|
13 => GroupType::Logoff(pdata),
|
|
14 => GroupType::Camera(pdata),
|
|
15 => GroupType::Static(pdata),
|
|
16 => GroupType::Tag(pdata),
|
|
n => return Err(ReprError::new(n).into()),
|
|
};
|
|
|
|
Ok((InterGroup{flags, ttype, lines, beg, len}, 12))
|
|
}
|
|
|
|
/// Reads a `Face`.
|
|
pub fn read_face(b: &[u8]) -> ResultS<(Face, usize)>
|
|
{
|
|
read_data! {
|
|
endian: BIG, buf: b, size: 6, start: 0, data {
|
|
let start = u16[0] usize;
|
|
let face = u16[2];
|
|
let color = u16[4];
|
|
}
|
|
}
|
|
|
|
Ok((Face{start, face, color}, 6))
|
|
}
|
|
|
|
/// Reads a `term` chunk.
|
|
pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
|
|
{
|
|
read_data! {
|
|
endian: BIG, buf: b, size: 10, start: 0, data {
|
|
let end = u16[0] usize;
|
|
let encoded = u16[2];
|
|
let lines = u16[4];
|
|
let group_n = u16[6] usize;
|
|
let face_n = u16[8] usize;
|
|
}
|
|
}
|
|
|
|
let encoded = encoded != 0;
|
|
|
|
let (i_grp, x) = rd_array_num(&b[10..], group_n, read_group)?;
|
|
let (faces, y) = rd_array_num(&b[10 + x..], face_n, read_face)?;
|
|
|
|
let text = ok!(b.get(10 + x + y..end), "not enough data")?;
|
|
let text = if encoded {fuck_string(text)} else {text.to_vec()};
|
|
|
|
let mut groups = Vec::with_capacity(group_n);
|
|
|
|
for grp in &i_grp {
|
|
let flags = grp.flags;
|
|
let ttype = grp.ttype;
|
|
let lines = grp.lines;
|
|
let beg = grp.beg;
|
|
let len = grp.len;
|
|
let text = ok!(text.get(beg..beg + len), "bad offset")?;
|
|
let text = mac_roman_cstr(text);
|
|
|
|
groups.push(Group{flags, ttype, lines, text});
|
|
}
|
|
|
|
Ok((Terminal{lines, groups, faces}, end))
|
|
}
|
|
|
|
impl Default for GroupType
|
|
{
|
|
fn default() -> Self {GroupType::Unfinished}
|
|
}
|
|
|
|
/// A terminal definition, with collections of groups and faces.
|
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
pub struct Terminal
|
|
{
|
|
pub lines: u16,
|
|
pub groups: Vec<Group>,
|
|
pub faces: Vec<Face>,
|
|
}
|
|
|
|
/// A text face.
|
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
pub struct Face
|
|
{
|
|
pub start: usize,
|
|
pub face: u16,
|
|
pub color: u16,
|
|
}
|
|
|
|
/// A terminal command grouping.
|
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
pub struct Group
|
|
{
|
|
pub flags: GroupFlags,
|
|
pub ttype: GroupType,
|
|
pub lines: u16,
|
|
pub text: String,
|
|
}
|
|
|
|
/// Interim structure.
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
pub struct InterGroup
|
|
{
|
|
pub flags: GroupFlags,
|
|
pub ttype: GroupType,
|
|
pub lines: u16,
|
|
pub beg: usize,
|
|
pub len: usize,
|
|
}
|
|
|
|
/// The command of a `Group`.
|
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum GroupType
|
|
{
|
|
Logon(u16),
|
|
Unfinished,
|
|
Success,
|
|
Failure,
|
|
Info,
|
|
End,
|
|
TeleInter(u16),
|
|
TeleIntra(u16),
|
|
Checkpoint(u16),
|
|
Sound(u16),
|
|
Movie(u16),
|
|
Track(u16),
|
|
Pict(u16),
|
|
Logoff(u16),
|
|
Camera(u16),
|
|
Static(u16),
|
|
Tag(u16),
|
|
}
|
|
|
|
bitflags! {
|
|
/// Flags for `Group`.
|
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
|
pub struct GroupFlags: u16
|
|
{
|
|
/// Draws the picture on the right.
|
|
const DRAW_ON_RIGHT = 1;
|
|
/// Draws the picture in the center.
|
|
const DRAW_CENTER = 1 << 1;
|
|
}
|
|
}
|
|
|
|
// EOF
|