more solid error checking
parent
ec106d3224
commit
cac672348d
|
@ -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 ###
|
||||||
|
|
||||||
|
|
|
@ -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,9 +83,8 @@ 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,
|
|
||||||
b'\r' => '\n',
|
|
||||||
c if c & 0x80 != 0 => TR[usize::from(c) & 0x7F],
|
c if c & 0x80 != 0 => TR[usize::from(c) & 0x7F],
|
||||||
|
b'\r' => '\n',
|
||||||
c => char::from(c),
|
c => char::from(c),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -91,6 +92,16 @@ pub fn mac_roman_conv(s: &[u8]) -> String
|
||||||
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"), "I’ve");
|
assert_eq!(mac_roman_conv(b"I\xd5ve"), "I’ve");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mac_roman_cstr_tests()
|
||||||
|
{
|
||||||
|
assert_eq!(mac_roman_cstr(b"I\xd5ve awaken\0e").unwrap(), "I’ve awaken");
|
||||||
|
}
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue