better c_array function

png-branch
an 2019-02-18 11:52:18 -05:00
parent 4c88a142fd
commit 3021e437d6
6 changed files with 106 additions and 175 deletions

View File

@ -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 ################################################################

View File

@ -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`.

View File

@ -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)?)?,
_ => (),
}
}

View File

@ -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

View File

@ -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;

View File

@ -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)]