better c_array function
parent
4c88a142fd
commit
3021e437d6
|
@ -13,6 +13,9 @@ Inc. et al. Igni Ferroque, Ferro, and Atque are owned by Gregory Smith
|
|||
(treellama.) Maraiah is owned by Project Golan. Any other copyrights belong to
|
||||
their respective owners.
|
||||
|
||||
If you need explanation on anything in this document don't hesitate to ask me.
|
||||
Contact information is available at <http://greyserv.net>.
|
||||
|
||||
# CONTENTS ####################################################################
|
||||
|
||||
| Title | Description |
|
||||
|
@ -374,12 +377,12 @@ main menu, and physics files. Here is a listing of all chunks used within them:
|
|||
| `NOTE` | Not analyzed (annotations) |
|
||||
| `OBJS` | Array of Objects |
|
||||
| `påth` | Not analyzed (å is $8C) (guardpaths) |
|
||||
| `Minf` | Static Map Info |
|
||||
| `Minf` | Static Map Info structure |
|
||||
| `plac` | Not analyzed (item placement) |
|
||||
| `door` | No test data (extra door data) |
|
||||
| `plat` | No test data (platform static data) |
|
||||
| `EPNT` | Array of Endpoints |
|
||||
| `medi` | Not analyzed (media) |
|
||||
| `medi` | Media (liquids) |
|
||||
| `ambi` | Not analyzed (ambient sounds) |
|
||||
| `bonk` | Not analyzed (random sounds) |
|
||||
| `term` | Array of Terminals |
|
||||
|
@ -586,7 +589,8 @@ Point is 4 bytes. A geometric point.
|
|||
|
||||
### Endpoint ###
|
||||
|
||||
Endpoint is 16 bytes. More advanced point structure.
|
||||
Endpoint is 16 bytes. A point structure which can be loaded directly into
|
||||
memory instead of being calculated at runtime.
|
||||
|
||||
| Name | Type | Offset |
|
||||
| ---- | ---- | ------ |
|
||||
|
@ -623,8 +627,9 @@ Line is 32 bytes. A geometric line segment.
|
|||
- `Flags` is a Line Flags bit field.
|
||||
- `HeightHi` and `HeightLo` are the highest adjacent ceiling and lowest
|
||||
adjacent floor heights, respectively.
|
||||
- `SideFrnt` and `SideBack` are the indices of the Sides in the front and back.
|
||||
- `PolyFrnt` and `PolyBack` are the indices of the connected Polygons.
|
||||
- `SideFrnt` and `SideBack` are Object ID indices of the Sides in the front and
|
||||
back.
|
||||
- `PolyFrnt` and `PolyBack` are Object ID indices of the connected Polygons.
|
||||
|
||||
### Side ###
|
||||
|
||||
|
@ -959,24 +964,6 @@ Header Op is 24 bytes.
|
|||
| `Bottom` | `u16` | `16` |
|
||||
| `Right` | `u16` | `18` |
|
||||
|
||||
### QuickTime Image ###
|
||||
|
||||
TODO
|
||||
|
||||
* 68 bytes
|
||||
|
||||
if matte:
|
||||
* U32: matte ID size
|
||||
* matte id size - 4 bytes
|
||||
|
||||
* U32: id size
|
||||
* char[4]: codec type
|
||||
* 36 bytes
|
||||
* U32: data size
|
||||
* 38 bytes
|
||||
* image data follows
|
||||
* some other bullshit
|
||||
|
||||
## Shapes ##
|
||||
|
||||
Shapes files start with exactly 32 Collection Headers, followed by everything
|
||||
|
@ -1183,7 +1170,7 @@ commands rather than just the header and sample data.)
|
|||
| `LoopEnd` | `u32` | `16` |
|
||||
| `Magic` | `u8` | `20` |
|
||||
|
||||
- If `Magic` is `$00` nothing else needs to be done and raw signed 8-bit mono
|
||||
- If `Magic` is `$00` nothing else needs to be done and raw unsigned 8-bit mono
|
||||
PCM sample data starts at byte 22. If it is `$FF` it is followed by a Carbon
|
||||
Extended Sound Header, or if it is `$FE` it is followed by a Carbon Compressed
|
||||
Sound Header. The compressed sound header is not documented because it is not
|
||||
|
@ -1205,8 +1192,9 @@ actually useful field.
|
|||
|
||||
- `Frames` is used instead of `Size` for sounds with this header, since it
|
||||
represents how many frames there are rather than how many bytes. Even though
|
||||
this is actually a pointless distinction and Size is left at 1 anyway.
|
||||
- `SampleBits` must be either 16 or 8.
|
||||
this is actually a pointless distinction and `Size` is left at `1` anyway.
|
||||
- `SampleBits` must be either `16` or `8`. If it is `16` then the sample data
|
||||
is signed 16-bit *little endian* mono PCM.
|
||||
|
||||
# ENUMERATIONS ################################################################
|
||||
|
||||
|
|
|
@ -100,27 +100,23 @@ pub fn o_i16b(b: &[u8], i: usize) -> Option<i16>
|
|||
}
|
||||
}
|
||||
|
||||
/// Reads an array of any type with the `ArrayRead` trait.
|
||||
pub fn c_array<T: ArrayRead>(b: &[u8]) -> ResultS<Vec<T>>
|
||||
/// Reads an array of any type.
|
||||
pub fn c_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
|
||||
where T: Sized,
|
||||
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
||||
{
|
||||
let mut v = Vec::with_capacity(b.len() / T::SIZE);
|
||||
let mut v = Vec::new();
|
||||
let mut p = 0;
|
||||
|
||||
while p < b.len() {
|
||||
v.push(T::read(&b[p..])?);
|
||||
p += T::SIZE;
|
||||
let (r, s) = read(&b[p..])?;
|
||||
v.push(r);
|
||||
p += s;
|
||||
}
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
/// Trait for any structure which can be deserialized from an array of bytes.
|
||||
pub trait ArrayRead: Sized
|
||||
{
|
||||
const SIZE: usize;
|
||||
fn read(b: &[u8]) -> ResultS<Self>;
|
||||
}
|
||||
|
||||
impl ObjID
|
||||
{
|
||||
/// Creates an `ObjID` from a `u16`.
|
||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -1,5 +1,5 @@
|
|||
use maraiah::{durandal::{bin::*, err::*, file::*, image::*, sound::*, text::*},
|
||||
marathon::{machdr, map, pict, shp, snd, term, wad}};
|
||||
marathon::{machdr, map, pict, shp, snd, trm, wad}};
|
||||
use std::{collections::HashSet,
|
||||
fs,
|
||||
io::{self, Write}};
|
||||
|
@ -51,11 +51,11 @@ fn dump_chunk(opt: &Options, cid: Ident, cnk: &[u8], eid: u16) -> ResultS<()>
|
|||
make_tga(&format!("{}/pict_{}.tga", opt.out_dir, eid), &im)?;
|
||||
}
|
||||
b"Minf" => make_yaml(opt, &map::read_minf(cnk)?)?,
|
||||
b"EPNT" => make_yaml(opt, &c_array::<map::Endpoint>(cnk)?)?,
|
||||
b"PNTS" => make_yaml(opt, &c_array::<map::Point>(cnk)?)?,
|
||||
b"LINS" => make_yaml(opt, &c_array::<map::Line>(cnk)?)?,
|
||||
b"SIDS" => make_yaml(opt, &c_array::<map::Side>(cnk)?)?,
|
||||
b"term" => make_yaml(opt, &term::read_term(cnk)?)?,
|
||||
b"EPNT" => make_yaml(opt, &c_array(cnk, map::read_epnt)?)?,
|
||||
b"PNTS" => make_yaml(opt, &c_array(cnk, map::read_pnts)?)?,
|
||||
b"LINS" => make_yaml(opt, &c_array(cnk, map::read_lins)?)?,
|
||||
b"SIDS" => make_yaml(opt, &c_array(cnk, map::read_sids)?)?,
|
||||
b"term" => make_yaml(opt, &c_array(cnk, trm::read_term)?)?,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,6 @@ use bitflags::bitflags;
|
|||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
|
||||
fn read_sidetex(b: &[u8]) -> ResultS<SideTex>
|
||||
{
|
||||
let offs = Point::read(c_data(b, 0..4)?)?;
|
||||
let tex_id = c_u16b(b, 4)?;
|
||||
let tex_id = ObjID::from_repr(tex_id);
|
||||
Ok(SideTex{offs, tex_id})
|
||||
}
|
||||
|
||||
pub fn read_minf(b: &[u8]) -> ResultS<Minf>
|
||||
{
|
||||
let env_code = c_u16b(b, 0)?;
|
||||
|
@ -29,93 +21,82 @@ pub fn read_minf(b: &[u8]) -> ResultS<Minf>
|
|||
levelnam})
|
||||
}
|
||||
|
||||
impl ArrayRead for Point
|
||||
pub fn read_sidetex(b: &[u8]) -> ResultS<SideTex>
|
||||
{
|
||||
const SIZE: usize = 4;
|
||||
|
||||
fn read(b: &[u8]) -> ResultS<Self>
|
||||
{
|
||||
let x = c_u16b(b, 0)?;
|
||||
let y = c_u16b(b, 2)?;
|
||||
let x = Unit::from_bits(x);
|
||||
let y = Unit::from_bits(y);
|
||||
Ok(Point{x, y})
|
||||
}
|
||||
let offs = read_point(c_data(b, 0..4)?)?;
|
||||
let tex_id = c_u16b(b, 4)?;
|
||||
let tex_id = ObjID::from_repr(tex_id);
|
||||
Ok(SideTex{offs, tex_id})
|
||||
}
|
||||
|
||||
impl ArrayRead for Endpoint
|
||||
pub fn read_point(b: &[u8]) -> ResultS<Point>
|
||||
{
|
||||
const SIZE: usize = 16;
|
||||
|
||||
fn read(b: &[u8]) -> ResultS<Self>
|
||||
{
|
||||
let flags = c_u16b(b, 0)?;
|
||||
let adj_hi = c_u16b(b, 2)?;
|
||||
let adj_lo = c_u16b(b, 4)?;
|
||||
let pos = Point::read(c_data(b, 6..10)?)?;
|
||||
let support = c_u16b(b, 14)?;
|
||||
let flags = ok!(EndpFlags::from_bits(flags), "bad EndpFlags")?;
|
||||
let adj_hi = Unit::from_bits(adj_hi);
|
||||
let adj_lo = Unit::from_bits(adj_lo);
|
||||
Ok(Endpoint{flags, adj_hi, adj_lo, pos, support})
|
||||
}
|
||||
let x = c_u16b(b, 0)?;
|
||||
let y = c_u16b(b, 2)?;
|
||||
let x = Unit::from_bits(x);
|
||||
let y = Unit::from_bits(y);
|
||||
Ok(Point{x, y})
|
||||
}
|
||||
|
||||
impl ArrayRead for Line
|
||||
pub fn read_epnt(b: &[u8]) -> ResultS<(Point, usize)>
|
||||
{
|
||||
const SIZE: usize = 32;
|
||||
|
||||
fn read(b: &[u8]) -> ResultS<Self>
|
||||
{
|
||||
let epnt_f = c_u16b(b, 0)?;
|
||||
let epnt_b = c_u16b(b, 2)?;
|
||||
let flags = c_u16b(b, 4)?;
|
||||
let length = c_u16b(b, 6)?;
|
||||
let adj_hi = c_u16b(b, 8)?;
|
||||
let adj_lo = c_u16b(b, 10)?;
|
||||
let side_f = c_u16b(b, 12)?;
|
||||
let side_b = c_u16b(b, 14)?;
|
||||
let poly_f = c_u16b(b, 16)?;
|
||||
let poly_b = c_u16b(b, 18)?;
|
||||
let flags = ok!(LineFlags::from_bits(flags), "bad LineFlags")?;
|
||||
let length = Unit::from_bits(length);
|
||||
let adj_hi = Unit::from_bits(adj_hi);
|
||||
let adj_lo = Unit::from_bits(adj_lo);
|
||||
Ok(Line{flags, length, adj_hi, adj_lo, epnt_f, epnt_b, side_f, side_b,
|
||||
poly_f, poly_b})
|
||||
}
|
||||
Ok((read_point(c_data(b, 6..10)?)?, 16))
|
||||
}
|
||||
|
||||
impl ArrayRead for Side
|
||||
pub fn read_pnts(b: &[u8]) -> ResultS<(Point, usize)>
|
||||
{
|
||||
const SIZE: usize = 64;
|
||||
Ok((read_point(b)?, 4))
|
||||
}
|
||||
|
||||
fn read(b: &[u8]) -> ResultS<Self>
|
||||
{
|
||||
let stype = c_u16b(b, 0)?;
|
||||
let flags = c_u16b(b, 2)?;
|
||||
let tex_pri = read_sidetex(c_data(b, 4..10)?)?;
|
||||
let tex_sec = read_sidetex(c_data(b, 10..16)?)?;
|
||||
let tex_tra = read_sidetex(c_data(b, 16..22)?)?;
|
||||
let ex_tleft = Point::read(c_data(b, 22..26)?)?;
|
||||
let ex_trigh = Point::read(c_data(b, 26..30)?)?;
|
||||
let ex_bleft = Point::read(c_data(b, 30..34)?)?;
|
||||
let ex_brigh = Point::read(c_data(b, 34..38)?)?;
|
||||
let paneltyp = c_u16b(b, 38)?;
|
||||
let paneldat = c_i16b(b, 40)?;
|
||||
let xfer_pri = c_u16b(b, 42)?;
|
||||
let xfer_sec = c_u16b(b, 44)?;
|
||||
let xfer_tra = c_u16b(b, 46)?;
|
||||
let shade = c_u32b(b, 48)?;
|
||||
let flags = ok!(SideFlags::from_bits(flags), "bad SideFlags")?;
|
||||
let xfer_pri = TransferMode::from_repr(xfer_pri)?;
|
||||
let xfer_sec = TransferMode::from_repr(xfer_sec)?;
|
||||
let xfer_tra = TransferMode::from_repr(xfer_tra)?;
|
||||
let shade = Fixed::from_bits(shade);
|
||||
Ok(Side{stype, flags, tex_pri, tex_sec, tex_tra, ex_tleft, ex_trigh,
|
||||
ex_bleft, ex_brigh, paneltyp, paneldat, xfer_pri, xfer_sec,
|
||||
xfer_tra, shade})
|
||||
}
|
||||
pub fn read_lins(b: &[u8]) -> ResultS<(Line, usize)>
|
||||
{
|
||||
let pnt_beg = c_u16b(b, 0)?;
|
||||
let pnt_end = c_u16b(b, 2)?;
|
||||
let flags = c_u16b(b, 4)?;
|
||||
let length = c_u16b(b, 6)?;
|
||||
let adj_hi = c_u16b(b, 8)?;
|
||||
let adj_lo = c_u16b(b, 10)?;
|
||||
let side_fr = c_u16b(b, 12)?;
|
||||
let side_bk = c_u16b(b, 14)?;
|
||||
let poly_fr = c_u16b(b, 16)?;
|
||||
let poly_bk = c_u16b(b, 18)?;
|
||||
let flags = ok!(LineFlags::from_bits(flags), "bad LineFlags")?;
|
||||
let length = Unit::from_bits(length);
|
||||
let adj_hi = Unit::from_bits(adj_hi);
|
||||
let adj_lo = Unit::from_bits(adj_lo);
|
||||
let side_fr = ObjID::from_repr(side_fr);
|
||||
let side_bk = ObjID::from_repr(side_bk);
|
||||
let poly_fr = ObjID::from_repr(poly_fr);
|
||||
let poly_bk = ObjID::from_repr(poly_bk);
|
||||
Ok((Line{flags, length, adj_hi, adj_lo, pnt_beg, pnt_end, side_fr,
|
||||
side_bk, poly_fr, poly_bk}, 32))
|
||||
}
|
||||
|
||||
pub fn read_sids(b: &[u8]) -> ResultS<(Side, usize)>
|
||||
{
|
||||
let stype = c_u16b(b, 0)?;
|
||||
let flags = c_u16b(b, 2)?;
|
||||
let tex_pri = read_sidetex(c_data(b, 4..10)?)?;
|
||||
let tex_sec = read_sidetex(c_data(b, 10..16)?)?;
|
||||
let tex_tra = read_sidetex(c_data(b, 16..22)?)?;
|
||||
let ex_tleft = read_point(c_data(b, 22..26)?)?;
|
||||
let ex_trigh = read_point(c_data(b, 26..30)?)?;
|
||||
let ex_bleft = read_point(c_data(b, 30..34)?)?;
|
||||
let ex_brigh = read_point(c_data(b, 34..38)?)?;
|
||||
let paneltyp = c_u16b(b, 38)?;
|
||||
let paneldat = c_i16b(b, 40)?;
|
||||
let xfer_pri = c_u16b(b, 42)?;
|
||||
let xfer_sec = c_u16b(b, 44)?;
|
||||
let xfer_tra = c_u16b(b, 46)?;
|
||||
let shade = c_u32b(b, 48)?;
|
||||
let flags = ok!(SideFlags::from_bits(flags), "bad SideFlags")?;
|
||||
let xfer_pri = TransferMode::from_repr(xfer_pri)?;
|
||||
let xfer_sec = TransferMode::from_repr(xfer_sec)?;
|
||||
let xfer_tra = TransferMode::from_repr(xfer_tra)?;
|
||||
let shade = Fixed::from_bits(shade);
|
||||
Ok((Side{stype, flags, tex_pri, tex_sec, tex_tra, ex_tleft, ex_trigh,
|
||||
ex_bleft, ex_brigh, paneltyp, paneldat, xfer_pri, xfer_sec,
|
||||
xfer_tra, shade}, 64))
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -125,29 +106,19 @@ pub struct Point
|
|||
y: Unit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Endpoint
|
||||
{
|
||||
flags: EndpFlags,
|
||||
adj_hi: Unit,
|
||||
adj_lo: Unit,
|
||||
pos: Point,
|
||||
support: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Line
|
||||
{
|
||||
flags: LineFlags,
|
||||
length: Unit,
|
||||
adj_hi: Unit,
|
||||
adj_lo: Unit,
|
||||
epnt_f: u16,
|
||||
epnt_b: u16,
|
||||
side_f: u16,
|
||||
side_b: u16,
|
||||
poly_f: u16,
|
||||
poly_b: u16,
|
||||
flags: LineFlags,
|
||||
length: Unit,
|
||||
adj_hi: Unit,
|
||||
adj_lo: Unit,
|
||||
pnt_beg: u16,
|
||||
pnt_end: u16,
|
||||
side_fr: ObjID,
|
||||
side_bk: ObjID,
|
||||
poly_fr: ObjID,
|
||||
poly_bk: ObjID,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
|
@ -189,16 +160,6 @@ pub struct Minf
|
|||
levelnam: String,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Serialize)]
|
||||
pub struct EndpFlags: u16
|
||||
{
|
||||
const Solid = 1;
|
||||
const SameHeight = 1 << 1;
|
||||
const Transparent = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Serialize)]
|
||||
pub struct LineFlags: u16
|
||||
|
|
|
@ -5,7 +5,7 @@ pub mod map;
|
|||
pub mod pict;
|
||||
pub mod shp;
|
||||
pub mod snd;
|
||||
pub mod term;
|
||||
pub mod trm;
|
||||
pub mod wad;
|
||||
pub mod xfer;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ fn read_face(b: &[u8]) -> ResultS<Face>
|
|||
Ok(Face { start, face, color })
|
||||
}
|
||||
|
||||
fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
|
||||
pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
|
||||
{
|
||||
const SIZE_GROUP: usize = 12;
|
||||
const SIZE_FACE: usize = 6;
|
||||
|
@ -62,21 +62,7 @@ fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)>
|
|||
p += SIZE_FACE;
|
||||
}
|
||||
|
||||
Ok((end, Terminal{lines, groups, faces}))
|
||||
}
|
||||
|
||||
pub fn read_term(b: &[u8]) -> ResultS<Vec<Terminal>>
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
let mut p = 0;
|
||||
|
||||
while p < b.len() {
|
||||
let (size, trm) = read_terminal(c_data(b, p..)?)?;
|
||||
v.push(trm);
|
||||
p += size;
|
||||
}
|
||||
|
||||
Ok(v)
|
||||
Ok((Terminal{lines, groups, faces}, end))
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
Loading…
Reference in New Issue