more solid error checking

png-branch
an 2019-03-04 07:28:04 -05:00
parent ec106d3224
commit cac672348d
6 changed files with 78 additions and 81 deletions

View File

@ -2170,8 +2170,6 @@ If `DataVersion` is `DataM1`, then `ItemOpt` must be set by the client.
| `TermPause` | `8` | | `TermPause` | `8` |
| `M1Monster` | `9` | | `M1Monster` | `9` |
| `M1Weps` | `10` | | `M1Weps` | `10` |
| `NetPlay` | `13` |
| `Solo` | `14` |
- `Vacuum` makes most weapons not work and oxygen deplete. - `Vacuum` makes most weapons not work and oxygen deplete.
- `Magnetic` fucks up the motion sensor. - `Magnetic` fucks up the motion sensor.
@ -2185,8 +2183,6 @@ If `DataVersion` is `DataM1`, then `ItemOpt` must be set by the client.
- `M1Monster` sets monster activation limits to Marathon 1's. - `M1Monster` sets monster activation limits to Marathon 1's.
- `M1Weps` changes weapon pickups on Total Carnage and makes grenades low - `M1Weps` changes weapon pickups on Total Carnage and makes grenades low
gravity. gravity.
- `NetPlay` marks the map as net-play compatible.
- `Solo` marks the map as solo compatible.
### Light Flags ### ### Light Flags ###

View File

@ -1,5 +1,7 @@
//! Text conversion utilities. //! Text conversion utilities.
use crate::durandal::err::*;
/// Dumps a slice of memory as text to stderr. /// Dumps a slice of memory as text to stderr.
pub fn dump_mem(b: &[u8]) pub fn dump_mem(b: &[u8])
{ {
@ -81,16 +83,25 @@ pub fn mac_roman_conv(s: &[u8]) -> String
for &c in s.iter() { for &c in s.iter() {
v.push(match c { v.push(match c {
0 => break, c if c & 0x80 != 0 => TR[usize::from(c) & 0x7F],
b'\r' => '\n', b'\r' => '\n',
c if c & 0x80 != 0 => TR[usize::from(c) & 0x7F], c => char::from(c),
c => char::from(c), });
});
} }
v v
} }
/// Converts a C-style string from Mac Roman to Unicode.
pub fn mac_roman_cstr(s: &[u8]) -> ResultS<String>
{
if let Some(s) = s.split(|&n| n == 0).nth(0) {
Ok(mac_roman_conv(s))
} else {
bail!("no null in C string");
}
}
const TR: [char; 128] = const TR: [char; 128] =
['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}', ['\u{00c4}', '\u{00c5}', '\u{00c7}', '\u{00c9}', '\u{00d1}', '\u{00d6}',
'\u{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}', '\u{00dc}', '\u{00e1}', '\u{00e0}', '\u{00e2}', '\u{00e4}', '\u{00e3}',
@ -139,4 +150,10 @@ fn mac_roman_conv_basic_marathon_stuff()
assert_eq!(mac_roman_conv(b"I\xd5ve"), "Ive"); assert_eq!(mac_roman_conv(b"I\xd5ve"), "Ive");
} }
#[test]
fn mac_roman_cstr_tests()
{
assert_eq!(mac_roman_cstr(b"I\xd5ve awaken\0e").unwrap(), "Ive awaken");
}
// EOF // EOF

View File

@ -1,6 +1,6 @@
//! Structures used by Marathon's Map format. //! Structures used by Marathon's Map format.
use crate::{durandal::{bin::*, err::*, fixed::*, text::mac_roman_conv}, use crate::{durandal::{bin::*, err::*, fixed::*, text::*},
marathon::xfer::TransferMode}; marathon::xfer::TransferMode};
use bitflags::bitflags; use bitflags::bitflags;
@ -55,13 +55,14 @@ pub fn read_minf(b: &[u8]) -> ResultS<Minf>
music_id = u16[4]; music_id = u16[4];
missi_flags = u16[6]; missi_flags = u16[6];
envir_flags = u16[8]; envir_flags = u16[8];
level_name = mac_roman_conv[18..84] no_try; level_name = mac_roman_cstr[18..84];
entry_flags = u32[84]; entry_flags = u32[84];
} }
let missi_flags = flag_ok!(MsnFlags, missi_flags)?; let missi_flags = flag_ok!(MsnFlags, missi_flags)?;
let envir_flags = flag_ok!(EnvFlags, envir_flags)?; let envir_flags = flag_ok!(EnvFlags, envir_flags)?;
let entry_flags = flag_ok!(EntFlags, entry_flags)?; let entry_flags = flag_ok!(EntFlags, entry_flags)?;
Ok(Minf{env_code, physi_id, music_id, missi_flags, envir_flags, entry_flags, Ok(Minf{env_code, physi_id, music_id, missi_flags, envir_flags, entry_flags,
level_name}) level_name})
} }
@ -397,7 +398,7 @@ pub fn read_note(b: &[u8]) -> ResultS<(Note, usize)>
72, BE in b => 72, BE in b =>
pos = read_point[2..6]; pos = read_point[2..6];
poly = u16[6]; poly = u16[6];
text = mac_roman_conv[8..72] no_try; text = mac_roman_cstr[8..72];
} }
Ok((Note{pos, poly, text}, 72)) Ok((Note{pos, poly, text}, 72))
@ -650,8 +651,6 @@ bitflags! {
const TermPause = 1 << 8; const TermPause = 1 << 8;
const M1Monster = 1 << 9; const M1Monster = 1 << 9;
const M1Weps = 1 << 10; const M1Weps = 1 << 10;
const NetPlay = 1 << 13;
const Solo = 1 << 14;
} }
} }

View File

@ -2,7 +2,6 @@
use crate::durandal::{err::*, text::*}; use crate::durandal::{err::*, text::*};
use bitflags::bitflags; use bitflags::bitflags;
use std::fmt;
/// Reads a `Group`. /// Reads a `Group`.
pub fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group> pub fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
@ -17,7 +16,7 @@ pub fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
lines = u16[10]; lines = u16[10];
} }
let text = mac_roman_conv(&text[start..start + size]); let text = mac_roman_cstr(&text[start..start + size])?;
let flags = flag_ok!(GroupFlags, flags)?; let flags = flag_ok!(GroupFlags, flags)?;
let ttype = GroupType::from_repr(ttype)?; let ttype = GroupType::from_repr(ttype)?;
@ -81,32 +80,32 @@ pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)>
} }
/// A terminal definition, with collections of groups and faces. /// A terminal definition, with collections of groups and faces.
#[derive(Debug, serde::Serialize)] #[derive(Debug, PartialEq, serde::Serialize)]
pub struct Terminal pub struct Terminal
{ {
lines: u16, pub lines: u16,
groups: Vec<Group>, pub groups: Vec<Group>,
faces: Vec<Face>, pub faces: Vec<Face>,
} }
/// A text face. /// A text face.
#[derive(Debug, serde::Serialize)] #[derive(Debug, PartialEq, serde::Serialize)]
pub struct Face pub struct Face
{ {
start: usize, pub start: usize,
face: u16, pub face: u16,
color: u16, pub color: u16,
} }
/// A terminal command grouping. /// A terminal command grouping.
#[derive(serde::Serialize)] #[derive(Debug, PartialEq, serde::Serialize)]
pub struct Group pub struct Group
{ {
flags: GroupFlags, pub flags: GroupFlags,
ttype: GroupType, pub ttype: GroupType,
pdata: i16, pub pdata: i16,
lines: u16, pub lines: u16,
text: String, pub text: String,
} }
bitflags! { bitflags! {
@ -121,7 +120,7 @@ bitflags! {
c_enum! { c_enum! {
/// The command of a `Group`. /// The command of a `Group`.
#[derive(Debug, serde::Serialize)] #[derive(Debug, PartialEq, serde::Serialize)]
pub enum GroupType: u16 pub enum GroupType: u16
{ {
0 => Logon, 0 => Logon,
@ -144,18 +143,4 @@ c_enum! {
} }
} }
impl fmt::Debug for Group
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "Group{{{:?} {} {}", self.ttype, self.pdata, self.lines)?;
if !self.text.is_empty() {
write!(f, ";\n{}", self.text)?;
}
write!(f, "}}")
}
}
// EOF // EOF

View File

@ -1,6 +1,6 @@
//! Marathon Wad format handling. //! Marathon Wad format handling.
use crate::{durandal::{bin::*, err::*, image, text::mac_roman_conv}, use crate::{durandal::{bin::*, err::*, image, text::mac_roman_cstr},
marathon::{map, phy, pict, trm}}; marathon::{map, phy, pict, trm}};
use std::collections::BTreeMap; use std::collections::BTreeMap;
@ -27,30 +27,30 @@ pub fn read_chunks(b: &[u8], old_dat: bool, siz_cnk: usize)
let data = &b[beg..end]; let data = &b[beg..end];
chunks.push(match &iden.0 { chunks.push(match &iden.0 {
b"PICT" => Chunk::Pict(pict::load_pict(data)?), b"PICT" => Chunk::Pict(pict::load_pict(data)?),
b"Minf" => Chunk::Minf(map::read_minf(data)?), b"Minf" => Chunk::Minf(map::read_minf(data)?),
b"iidx" => Chunk::Iidx(rd_array(data, map::read_iidx)?), b"iidx" => Chunk::Iidx(rd_array(data, map::read_iidx)?),
b"EPNT" => Chunk::Pnts(rd_array(data, map::read_epnt)?), b"EPNT" => Chunk::Pnts(rd_array(data, map::read_epnt)?),
b"PNTS" => Chunk::Pnts(rd_array(data, map::read_pnts)?), b"PNTS" => Chunk::Pnts(rd_array(data, map::read_pnts)?),
b"LINS" => Chunk::Lins(rd_array(data, map::read_lins)?), b"LINS" => Chunk::Lins(rd_array(data, map::read_lins)?),
b"SIDS" => Chunk::Sids(rd_array(data, map_read_sides)?), b"SIDS" => Chunk::Sids(rd_array(data, map_read_sides)?),
b"POLY" => Chunk::Poly(rd_array(data, map_read_polys)?), b"POLY" => Chunk::Poly(rd_array(data, map_read_polys)?),
b"OBJS" => Chunk::Objs(rd_array(data, map::read_objs)?), b"OBJS" => Chunk::Objs(rd_array(data, map::read_objs)?),
b"LITE" => Chunk::Lite(rd_array(data, map_read_light)?), b"LITE" => Chunk::Lite(rd_array(data, map_read_light)?),
b"plac" => Chunk::Plac(rd_array(data, map::read_plac)?), b"plac" => Chunk::Plac(rd_array(data, map::read_plac)?),
b"ambi" => Chunk::Ambi(rd_array(data, map::read_ambi)?), b"ambi" => Chunk::Ambi(rd_array(data, map::read_ambi)?),
b"bonk" => Chunk::Bonk(rd_array(data, map::read_bonk)?), b"bonk" => Chunk::Bonk(rd_array(data, map::read_bonk)?),
b"medi" => Chunk::Medi(rd_array(data, map::read_medi)?), b"medi" => Chunk::Medi(rd_array(data, map::read_medi)?),
b"plat" => Chunk::Plat(rd_array(data, map::read_plat)?), b"plat" => Chunk::Plat(rd_array(data, map::read_plat)?),
b"NOTE" => Chunk::Note(rd_array(data, map::read_note)?), b"NOTE" => Chunk::Note(rd_array(data, map::read_note)?),
b"term" => Chunk::Term(rd_array(data, trm::read_term)?), b"term" => Chunk::Term(rd_array(data, trm::read_term)?),
b"FXpx" => Chunk::Fxpx(rd_array(data, phy::read_fxpx)?), b"FXpx" => Chunk::Fxpx(rd_array(data, phy::read_fxpx)?),
b"MNpx" => Chunk::Mnpx(rd_array(data, phy::read_mnpx)?), b"MNpx" => Chunk::Mnpx(rd_array(data, phy::read_mnpx)?),
b"PRpx" => Chunk::Prpx(rd_array(data, phy::read_prpx)?), b"PRpx" => Chunk::Prpx(rd_array(data, phy::read_prpx)?),
b"PXpx" => Chunk::Pxpx(rd_array(data, phy::read_pxpx)?), b"PXpx" => Chunk::Pxpx(rd_array(data, phy::read_pxpx)?),
b"WPpx" => Chunk::Wppx(rd_array(data, phy::read_wppx)?), b"WPpx" => Chunk::Wppx(rd_array(data, phy::read_wppx)?),
_ => Chunk::Data{iden, data: data.to_vec()}, _ => Chunk::Data{iden, data: data.to_vec()},
}); });
p = end; p = end;
} }
@ -104,7 +104,7 @@ pub fn read_wad(b: &[u8]) -> ResultS<Wad>
128, BE in b => 128, BE in b =>
ver_wad = u16[0]; ver_wad = u16[0];
ver_dat = u16[2]; ver_dat = u16[2];
name = mac_roman_conv[4..68] no_try; name = mac_roman_cstr[4..68];
siz_app = u16[78] usize; siz_app = u16[78] usize;
siz_wcnk = u16[80] usize; siz_wcnk = u16[80] usize;
siz_went = u16[82] usize; siz_went = u16[82] usize;

View File

@ -22,21 +22,21 @@ fn mk_draw_area(b: &gtk::Builder)
let im = CairoPixbuf(load_img("/net/greyserv/maraiah/tycho/tycho1")); let im = CairoPixbuf(load_img("/net/greyserv/maraiah/tycho/tycho1"));
area.connect_draw(move |area, cr| { area.connect_draw(move |area, cr| {
let w = f64::from(area.get_allocated_width()); let w = f64::from(area.get_allocated_width());
let h = f64::from(area.get_allocated_height()); let h = f64::from(area.get_allocated_height());
ax.set_lower(0.0); ax.set_lower(0.0);
ax.set_upper(w); ax.set_upper(w);
ay.set_lower(0.0); ay.set_lower(0.0);
ay.set_upper(h); ay.set_upper(h);
let d = CairoDrawArea::new(cr.clone(), w, h); let d = CairoDrawArea::new(cr.clone(), w, h);
draw_map_none(&d, &im); draw_map_none(&d, &im);
Inhibit(true) Inhibit(true)
}); });
} }
fn run_app(app: &gtk::Application) fn run_app(app: &gtk::Application)