Add terminal format loading
parent
7e8c28b6ca
commit
37e1c765d1
17
src/main.rs
17
src/main.rs
|
@ -7,12 +7,13 @@ pub mod marathon;
|
|||
use std::{io, fs, env};
|
||||
use std::io::Write;
|
||||
|
||||
use memmap::Mmap;
|
||||
|
||||
use marathon::wad;
|
||||
use durandal::pict::load_pict;
|
||||
use durandal::image::Image;
|
||||
|
||||
use marathon::{wad, term};
|
||||
|
||||
use memmap::Mmap;
|
||||
|
||||
fn write_ppm(fname: &str, im: &Image) -> io::Result<()>
|
||||
{
|
||||
let out = fs::File::create(fname)?;
|
||||
|
@ -38,13 +39,13 @@ fn main() -> io::Result<()>
|
|||
let mm = unsafe{Mmap::map(&fp)?};
|
||||
let wad = wad::Wad::new(&mm);
|
||||
|
||||
println!("{:?}", wad);
|
||||
println!("{:#?}", wad);
|
||||
|
||||
for (id, ent) in wad.ent
|
||||
{
|
||||
if let Some(c) = ent.map.get(b"PICT")
|
||||
if let Some(b) = ent.map.get(b"PICT")
|
||||
{
|
||||
let im = load_pict(c);
|
||||
let im = load_pict(b);
|
||||
match im {
|
||||
Ok(im) => {
|
||||
println!("entry {} has PICT {}x{}", id, im.w(), im.h());
|
||||
|
@ -53,6 +54,10 @@ fn main() -> io::Result<()>
|
|||
Err(e) => println!("entry {} has PICT (invalid: {:?})", id, e),
|
||||
}
|
||||
}
|
||||
else if let Some(b) = ent.map.get(b"term")
|
||||
{
|
||||
println!("entry {} has term {:#?}", id, term::Terminal::chunk(b));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Library for Marathon data formats.
|
||||
|
||||
pub mod term;
|
||||
pub mod wad;
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
use std::fmt;
|
||||
|
||||
use durandal::text::*;
|
||||
use durandal::bin::*;
|
||||
|
||||
impl Terminal
|
||||
{
|
||||
pub fn read(b: &[u8]) -> (usize, Terminal)
|
||||
{
|
||||
const SIZE_HEAD : usize = 10;
|
||||
const SIZE_GROUP: usize = 12;
|
||||
const SIZE_FACE : usize = 6;
|
||||
|
||||
let len = b_u16b(&b[ .. 2]) as usize;
|
||||
let enc = b_u16b(&b[2.. 4]) & 1 != 0;
|
||||
let lns = b_u16b(&b[4.. 6]);
|
||||
let gnu = b_u16b(&b[6.. 8]) as usize;
|
||||
let fnu = b_u16b(&b[8..10]) 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_u16b(&b[p ..p+ 2]);
|
||||
let typ = b_u16b(&b[p+ 2..p+ 4]).into();
|
||||
let per = b_i16b(&b[p+ 4..p+ 6]);
|
||||
let beg = b_u16b(&b[p+ 6..p+ 8]) as usize;
|
||||
let len = b_u16b(&b[p+ 8..p+10]) as usize;
|
||||
let lns = b_u16b(&b[p+10..p+12]);
|
||||
|
||||
let sta = end + beg;
|
||||
|
||||
let txt = &b[sta..sta+len];
|
||||
let txt = if enc {fuck_string(txt)} else {txt.to_vec()};
|
||||
let txt = mac_roman_conv(&txt);
|
||||
|
||||
grp.push(Group{typ, per, lns, txt});
|
||||
|
||||
p += SIZE_GROUP;
|
||||
}
|
||||
|
||||
for _ in 0..fnu
|
||||
{
|
||||
let ind = b_u16b(&b[p ..p+2]);
|
||||
let fce = b_u16b(&b[p+2..p+4]);
|
||||
let col = b_u16b(&b[p+4..p+6]);
|
||||
|
||||
fcs.push(Face{ind, fce, col});
|
||||
|
||||
p += SIZE_FACE;
|
||||
}
|
||||
|
||||
(len, Terminal{lns, grp, fcs})
|
||||
}
|
||||
|
||||
pub fn chunk(b: &[u8]) -> 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;
|
||||
}
|
||||
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Terminal
|
||||
{
|
||||
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
|
Loading…
Reference in New Issue