documentation

png-branch
an 2019-03-09 17:03:20 -05:00
parent 152d8a0b60
commit b5dfcf3ee2
16 changed files with 201 additions and 128 deletions

View File

@ -466,7 +466,7 @@ impl fmt::Debug for Ident
/// ```
#[derive(Clone, Copy, Default, PartialEq)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Ident(pub [u8; 4]);
pub struct Ident(/** The individual bytes of this identifier. */ pub [u8; 4]);
/// An object identified by a `u16` which may be `u16::max_value()` to
/// represent a nulled value.

View File

@ -38,7 +38,7 @@ macro_rules! c_enum
$(#[$outer:meta])*
$vi:vis enum $t:ident: $ti:ty
{
$($va:expr => $en:ident,)+
$($(#[$inner:meta])* $va:expr => $en:ident,)+
}
) => {
$(#[$outer])*
@ -54,8 +54,8 @@ macro_rules! c_enum
$vi fn from_repr(n: $ti) -> Result<Self, ReprError>
{
match n {
$($va => Ok($t::$en),)+
n => Err(ReprError::new(n))
$($(#[$inner])* $va => Ok($t::$en),)+
n => Err(ReprError::new(n))
}
}
}

View File

@ -30,8 +30,7 @@ fn crc_init() -> [u32; 256]
pub fn crc32(b: &[u8], s: u32) -> u32
{
let t = crc_init();
!b.iter()
.fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)])
!b.iter().fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)])
}
// EOF

View File

@ -237,8 +237,10 @@ pub struct Color8(u8, u8, u8);
#[derive(Debug, serde::Serialize)]
pub struct Image16
{
w: usize,
h: usize,
w: usize,
h: usize,
/// The raw color data for this image.
pub cr: Vec<Color16>,
}
@ -246,8 +248,10 @@ pub struct Image16
#[derive(Debug, serde::Serialize)]
pub struct Image8
{
w: usize,
h: usize,
w: usize,
h: usize,
/// The raw color data for this image.
pub cr: Vec<Color8>,
}

View File

@ -126,9 +126,11 @@ impl Sound for Sound16
/// A 16-bit PCM stream.
pub struct Sound16
{
rate: u16,
lp_beg: usize,
lp_end: usize,
rate: u16,
lp_beg: usize,
lp_end: usize,
/// The raw signed PCM data of this sound.
pub data: Vec<i16>,
}

View File

@ -32,12 +32,8 @@ fn process_wad(opt: &Options, b: &[u8]) -> ResultS<()>
{
let wad = wad::read_wad(b)?;
if opt.wad_header {
make_yaml(opt, &wad.head)?;
}
if opt.wad_wrt_all {
make_yaml(opt, &wad.entries)?;
make_yaml(opt, &wad)?;
}
Ok(())
@ -106,22 +102,10 @@ fn dump_sounds(opt: &Options, st: &snd::SoundTable, c: usize) -> ResultS<()>
Ok(())
}
fn write_sounds(opt: &Options, st: &snd::SoundTable) -> ResultS<()>
{
if opt.snd_write {
for sd in st.values() {
make_yaml(opt, &sd.header)?;
}
}
Ok(())
}
fn process_snd(opt: &Options, b: &[u8]) -> ResultS<()>
{
for (c, st) in snd::read_sounds(b)?.iter().enumerate() {
dump_sounds(opt, st, c)?;
write_sounds(opt, st)?;
}
Ok(())
@ -178,11 +162,6 @@ fn main() -> ResultS<()>
StoreTrue,
"shp: Dump all sequences as YAML to standard output");
arg!("--snd-write",
opt.snd_write,
StoreTrue,
"snd: Dump all sound headers as YAML to standard output");
arg!("--snd-dump",
opt.snd_dump,
StoreTrue,
@ -193,11 +172,6 @@ fn main() -> ResultS<()>
StoreTrue,
"wad: Dump all known chunks");
arg!("--wad-write-header",
opt.wad_header,
StoreTrue,
"wad: Dump header info as YAML to standard output");
arg!("--out-dir",
opt.out_dir,
Store,
@ -255,9 +229,7 @@ struct Options
shp_frm: bool,
shp_seq: bool,
snd_dump: bool,
snd_write: bool,
wad_wrt_all: bool,
wad_header: bool,
}
// EOF

View File

@ -1,9 +1,9 @@
#![deny(anonymous_parameters)]
#![deny(bare_trait_objects)]
#![deny(elided_lifetimes_in_paths)]
#![deny(unreachable_pub)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![deny(unreachable_pub)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![deny(clippy::all)]
@ -19,7 +19,6 @@
#![deny(clippy::filter_map)]
#![deny(clippy::float_arithmetic)]
#![deny(clippy::float_cmp_const)]
#![deny(clippy::if_not_else)]
#![deny(clippy::invalid_upcast_comparisons)]
#![deny(clippy::items_after_statements)]
#![deny(clippy::large_digit_groups)]

View File

@ -936,6 +936,7 @@ c_enum! {
}
}
/// The number of game ticks per second.
pub const TICKS_PER_SECOND: u16 = 30;
const OLD_LIGHT_DEFINITIONS: [Light; 8] = [

View File

@ -9,21 +9,23 @@ fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()>
{
read_data! {
8, BE in b =>
l = u8[0];
i = u8[1];
r = u16[2];
g = u16[4];
b = u16[6];
flag = u8[0];
ind = u8[1];
r = u16[2];
g = u16[4];
b = u16[6];
}
let l = match l {
128 => Ok(true),
0 => Ok(false),
_ => Err(err_msg("invalid flag in color")),
}?;
let cr = ok!(clut.get_mut(usize::from(ind)), "bad index")?;
*cr = match flag {
128 => ColorShp::Lit {r, g, b},
0 => ColorShp::Opaque{r, g, b},
_ => {
return Err(err_msg("invalid flag in color"));
}
};
let cr = ColorShp::Opaque{r, g, b, l};
*ok!(clut.get_mut(usize::from(i)), "bad index")? = cr;
Ok(())
}
@ -285,6 +287,7 @@ impl Color for ColorShp
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{r, ..} => r,
ColorShp::Lit {r, ..} => r,
}
}
@ -293,6 +296,7 @@ impl Color for ColorShp
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{g, ..} => g,
ColorShp::Lit {g, ..} => g,
}
}
@ -301,6 +305,7 @@ impl Color for ColorShp
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{b, ..} => b,
ColorShp::Lit {b, ..} => b,
}
}
@ -309,6 +314,7 @@ impl Color for ColorShp
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{..} => u16::max_value(),
ColorShp::Lit {..} => u16::max_value(),
}
}
}
@ -317,14 +323,18 @@ impl Color for ColorShp
#[derive(Copy, Clone, Debug, serde::Serialize)]
pub enum ColorShp
{
/// A completely translucent color.
Translucent,
Opaque
{
r: u16,
g: u16,
b: u16,
l: bool,
},
/// An opaque color which may be shaded.
Opaque{/** The red component. */ r: u16,
/** The green component. */ g: u16,
/** The blue component. */ b: u16},
/// An opaque color which may not be shaded.
Lit{/** The red component. */ r: u16,
/** The green component. */ g: u16,
/** The blue component. */ b: u16},
}
/// An unpacked Shape bitmap.
@ -350,42 +360,89 @@ pub struct ImageShp<'a, 'b>
#[derive(Debug, serde::Serialize)]
pub struct Frame
{
flags: FrameFlags,
min_lt: Fixed,
bmp_ind: usize,
wrl_l: Unit,
wrl_r: Unit,
wrl_t: Unit,
wrl_b: Unit,
wrl_x: Unit,
wrl_y: Unit,
/// The flags for this frame.
pub flags: FrameFlags,
/// The minimum light level for this frame.
pub min_lt: Fixed,
/// The index of the bitmap this frame uses.
pub bmp_ind: usize,
/// The left translation for this frame.
pub wrl_l: Unit,
/// The right translation for this frame.
pub wrl_r: Unit,
/// The top translation for this frame.
pub wrl_t: Unit,
/// The bottom translation for this frame.
pub wrl_b: Unit,
/// The X translation for this frame.
pub wrl_x: Unit,
/// The Y translation for this frame.
pub wrl_y: Unit,
}
/// A sequence, also known as a high level shape.
#[derive(Debug, serde::Serialize)]
pub struct Sequence
{
name: String,
v_type: ViewType,
frames: u16,
ticks: u16,
key: u16,
xfer: TransferMode,
xfer_pd: u16,
snd_beg: OptU16,
snd_key: OptU16,
snd_end: OptU16,
loop_f: u16,
/// The display name for this sequence.
pub name: String,
/// The view type for each frame in this sequence.
pub v_type: ViewType,
/// The number of frames in this sequence.
pub frames: u16,
/// The number of ticks each frame in this sequence takes.
pub ticks: u16,
/// The key frame index for this sequence.
pub key: u16,
/// The transfer mode to play over this sequence.
pub xfer: TransferMode,
/// The period in game ticks the transfer mode plays over.
pub xfer_pd: u16,
/// The sound to play at the beginning of this sequence.
pub snd_beg: OptU16,
/// The sound to play at the key frame of this sequence.
pub snd_key: OptU16,
/// The sound to play at the end of this sequence.
pub snd_end: OptU16,
/// Which frame to loop on.
pub loop_f: u16,
}
/// A collection of color tables, bitmaps, frames and sequences.
#[derive(Debug)]
pub struct Collection
{
/// The type of collection this is.
pub ctyp: CollectionType,
/// All of the color tables in this collection.
pub tabs: Vec<Vec<ColorShp>>,
/// All of the bitmaps in this collection.
pub bmps: Vec<Bitmap>,
/// All of the frames in this collection.
pub frms: Vec<Frame>,
/// All of the sequences in this collection.
pub seqs: Vec<Sequence>,
}
@ -405,8 +462,11 @@ bitflags! {
#[derive(serde::Serialize)]
pub struct FrameFlags: u16
{
/// The player's torso will obscure the player's legs.
const OBSCURE = 1 << 13;
/// The bitmap will be flipped on the vertical axis.
const FLIP_Y = 1 << 14;
/// The bitmap will be flipped on the horizontal axis.
const FLIP_X = 1 << 15;
}
}

View File

@ -78,10 +78,10 @@ pub fn read_sound_def(b: &[u8]) -> ResultS<Option<(Vec<usize>, u16, SoundDef)>>
p += 4;
}
let header = SoundHead{volume, flags, chance, pitch_lo, pitch_hi};
let sounds = Vec::with_capacity(n_sounds);
Ok(Some((ofs, index, SoundDef{header, sounds})))
Ok(Some((ofs, index,
SoundDef{volume, flags, chance, pitch_lo, pitch_hi, sounds})))
}
/// Reads all sounds from a Sound file.
@ -123,21 +123,25 @@ pub fn read_sounds(b: &[u8]) -> ResultS<Vec<SoundTable>>
Ok(sc)
}
/// The header of a sound definition.
#[derive(Debug, serde::Serialize)]
pub struct SoundHead
{
pub volume: Volume,
pub flags: SoundFlags,
pub chance: u16,
pub pitch_lo: Fixed,
pub pitch_hi: Fixed,
}
/// A sound definition containing one, many or no sounds.
pub struct SoundDef
{
pub header: SoundHead,
/// The volume type for this sound.
pub volume: Volume,
/// The flags for this sound.
pub flags: SoundFlags,
/// The chance out of `u16::max_value()` that this sound will not play.
pub chance: u16,
/// The low random pitch bound.
pub pitch_lo: Fixed,
/// The high random pitch bound.
pub pitch_hi: Fixed,
/// All of the sounds in this collection.
pub sounds: Vec<Sound16>,
}
@ -145,16 +149,23 @@ pub struct SoundDef
pub type SoundTable = BTreeMap<u16, SoundDef>;
bitflags! {
/// Flags for `SoundHead`.
/// Flags for `SoundDef`.
#[derive(serde::Serialize)]
pub struct SoundFlags: u16
{
/// The sound will not restart when trying to play over itself.
const NO_RESTART = 1;
/// The sound will not switch channels when trying to play over itself.
const NO_CHANNEL_SWITCH = 1 << 1;
/// The pitch variance will be halved.
const LESS_PITCH_CHANGE = 1 << 2;
/// The pitch variance will be nullified.
const NO_PITCH_CHANGE = 1 << 3;
/// The sound will play even when completely obstructed by walls.
const NO_OBSTRUCTION = 1 << 4;
/// The sound will play even when completely obstructed by media.
const NO_MEDIA_OBSTRUCT = 1 << 5;
/// The sound will have special stereo effects.
const AMBIENT = 1 << 6;
}
}

View File

@ -128,11 +128,11 @@ pub struct Group
#[derive(Debug)]
pub struct InterGroup
{
flags: GroupFlags,
ttype: GroupType,
lines: u16,
beg: usize,
len: usize,
pub flags: GroupFlags,
pub ttype: GroupType,
pub lines: u16,
pub beg: usize,
pub len: usize,
}
/// The command of a `Group`.
@ -163,7 +163,9 @@ bitflags! {
#[derive(Default, 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;
}
}

View File

@ -111,13 +111,11 @@ pub fn read_wad(b: &[u8]) -> ResultS<Wad>
siz_went = u16[82] usize;
}
let ver_wad = Ver::from_repr(ver_wad)?;
let old_wad = match ver_wad {
let old_dat = ver_dat == 0;
let old_wad = match Ver::from_repr(ver_wad)? {
Ver::Base => true,
_ => false,
};
let old_dat = ver_dat == 0;
let siz_ent = if old_wad {8 } else {10};
let siz_cnk = if old_wad {12} else {16};
@ -132,60 +130,82 @@ pub fn read_wad(b: &[u8]) -> ResultS<Wad>
let entries = read_entries(b, old_wad, old_dat, siz_app, siz_ent, siz_cnk)?;
Ok(Wad{head: WadHeader{ver_wad, old_dat, siz_app, name}, entries})
Ok(Wad{name, siz_app, entries})
}
/// Any kind of chunk in an `Entry`.
#[derive(Debug, serde::Serialize)]
pub enum Chunk
{
/// A `PICT` chunk.
Pict(image::Image8),
/// A `Minf` chunk.
Minf(map::Minf),
/// An `iidx` chunk.
Iidx(Vec<u16>),
/// A `PNTS` chunk.
Pnts(Vec<map::Point>),
/// A `LINS` chunk.
Lins(Vec<map::Line>),
/// A `SIDS` chunk.
Sids(Vec<map::Side>),
/// A `POLY` chunk.
Poly(Vec<map::Polygon>),
/// A `LITE` chunk.
Lite(Vec<map::Light>),
/// An `OBJS` chunk.
Objs(Vec<map::Object>),
/// A `plac` chunk.
Plac(Vec<map::ObjectFreq>),
/// An `ambi` chunk.
Ambi(Vec<map::SoundAmbi>),
/// A `bonk` chunk.
Bonk(Vec<map::SoundRand>),
/// A `medi` chunk.
Medi(Vec<map::Media>),
/// A `plat` chunk.
Plat(Vec<map::Platform>),
/// A `NOTE` chunk.
Note(Vec<map::Note>),
/// A `term` chunk.
Term(Vec<trm::Terminal>),
/// A `FXpx` chunk.
Fxpx(Vec<phy::Effect>),
/// A `MNpx` chunk.
Mnpx(Vec<phy::Monster>),
/// A `PRpx` chunk.
Prpx(Vec<phy::Projectile>),
/// A `PXpx` chunk.
Pxpx(Vec<phy::Physics>),
/// A `WPpx` chunk.
Wppx(Vec<phy::Weapon>),
Data{iden: Ident, data: Vec<u8>},
/// Any other type of chunk, which may have arbitrary data in it.
Data{/** The name of the chunk. */ iden: Ident,
/** The data. */ data: Vec<u8>},
}
/// An entry containing chunks and application-specific data.
#[derive(Debug, serde::Serialize)]
pub struct Entry
{
pub chunks: Vec<Chunk>,
pub appdata: Vec<u8>,
}
/// All of the chunks in this `Entry`.
pub chunks: Vec<Chunk>,
/// The header of a `Wad`.
#[derive(Debug, serde::Serialize)]
pub struct WadHeader
{
pub ver_wad: Ver,
pub old_dat: bool,
pub name: String,
pub siz_app: usize,
/// The application specific data for this Entry.
pub appdata: Vec<u8>,
}
/// A Map file containing entries.
#[derive(Debug, serde::Serialize)]
pub struct Wad
{
pub head: WadHeader,
/// The original name of this file.
pub name: String,
/// The size of each `Entry`'s `appdata` field.
pub siz_app: usize,
/// All of the entries in this `Wad`.
pub entries: BTreeMap<u16, Entry>,
}

View File

@ -47,9 +47,16 @@ pub type Point = (Coord, Coord);
#[derive(Copy, Clone, Debug)]
pub struct Rect
{
/// The horizontal coordinate to start at, from the left.
pub x: Coord,
/// The vertical coordinate to start at, from the top.
pub y: Coord,
/// The width of the rectangle.
pub w: Coord,
/// The height of the rectangle.
pub h: Coord,
}

View File

@ -30,7 +30,6 @@ fn read_epnt_must_process()
#[test]
fn map_must_not_process()
{
// these functions must not succeed
for inp in &RANDOM {
assert!(map::read_minf(inp).is_err());
assert!(map::read_old_minf(inp).is_err());
@ -50,9 +49,8 @@ fn map_must_not_process()
#[test]
#[allow(unused_must_use)]
fn map_wont_panic()
fn map_must_not_panic()
{
// these functions can succeed but must never panic
for inp in &RANDOM {
bin::rd_array(inp, map::read_ambi);
bin::rd_array(inp, map::read_bonk);

View File

@ -5,7 +5,6 @@ include!("data/rand.rs");
#[test]
fn phy_must_not_process()
{
// these functions must not succeed
for inp in &RANDOM {
assert!(bin::rd_array(inp, phy::read_fxpx).is_err());
assert!(bin::rd_array(inp, phy::read_mnpx).is_err());
@ -16,9 +15,8 @@ fn phy_must_not_process()
#[test]
#[allow(unused_must_use)]
fn phy_wont_panic()
fn phy_must_not_panic()
{
// these functions can succeed but must never panic
for inp in &RANDOM {
bin::rd_array(inp, phy::read_pxpx);
}

View File

@ -37,7 +37,7 @@ fn trm_must_not_process()
#[test]
#[allow(unused_must_use)]
fn trm_wont_panic()
fn trm_must_not_panic()
{
for inp in &RANDOM {
bin::rd_array(inp, trm::read_face);