Skip to content

Commit

Permalink
fix: serialization issues
Browse files Browse the repository at this point in the history
  • Loading branch information
francisdb committed Mar 21, 2024
1 parent f05cd32 commit 767184b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 19 deletions.
15 changes: 13 additions & 2 deletions src/vpx/biff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ impl<'a> BiffReader<'a> {
}

pub fn get_bool(&mut self) -> bool {
let all = &self.data[self.pos..self.pos + 4];
// Any other value is suspicious as it is not a boolean
if all != [0, 0, 0, 0] && all != [1, 0, 0, 0] {
panic!("Unexpected bytes for bool: {:?}", all);
}
let b = self.data[self.pos] != 0;
self.pos += 4;
self.bytes_in_record_remaining -= 4;
Expand Down Expand Up @@ -144,10 +149,16 @@ impl<'a> BiffReader<'a> {
}

pub fn get_f32(&mut self) -> f32 {
let i: Result<(&[u8], f32), nom::Err<()>> = le_f32(&self.data[self.pos..]);
let data = &self.data[self.pos..self.pos + 4];
let i: Result<(&[u8], f32), nom::Err<()>> = le_f32(data);
self.pos += 4;
self.bytes_in_record_remaining -= 4;
i.unwrap().1

let res = i.unwrap().1;
if res.is_nan() {
eprintln!("NaN value found in f32 for tag {}: {:?}", self.tag, data);
}
res
}

pub fn get_str(&mut self, count: usize) -> String {
Expand Down
39 changes: 24 additions & 15 deletions src/vpx/gamedata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use super::{
};
use crate::vpx::biff::{BiffRead, BiffWrite};
use crate::vpx::color::{Color, ColorJson};
use crate::vpx::json::F32WithNanInf;
use crate::vpx::material::{Material, SaveMaterial, SavePhysicsMaterial};
use crate::vpx::math::{dequantize_u8, quantize_u8};
use crate::vpx::renderprobe::RenderProbeWithGarbage;
Expand Down Expand Up @@ -221,7 +222,11 @@ pub struct GameData {
pub custom_colors: [Color; 16], //[Color; 16], // CCUS 113
pub protection_data: Option<Vec<u8>>, // SECB (removed in ?)
pub code: StringWithEncoding, // CODE 114
pub is_locked: Option<bool>, // TLCK (added in 10.8 for tournament mode?)
/// TLCK (added in 10.8 for tournament mode?)
/// Flag that disables all table edition. Lock toggles are counted to identify
/// version changes in a table (for example to guarantee untouched table for tournament)
/// Used to be a boolean for a while in the 10.8 dev cycle but now is a lock counter.
pub locked: Option<u32>, // TLCK (added in 10.8 for tournament mode?)
// This is a bit of a hack because we want reproducible builds.
// 10.8.0 beta 1-4 had EFSS at the old location, but it was moved to the new location in beta 5
// Some tables were released with these old betas, so we need to support both locations to be 100% reproducing the orignal table
Expand Down Expand Up @@ -281,10 +286,10 @@ pub(crate) struct GameDataJson {
pub bg_layback_full_single_screen: Option<f32>,
pub bg_fov_full_single_screen: Option<f32>,
pub bg_offset_x_full_single_screen: Option<f32>,
pub bg_offset_y_full_single_screen: Option<f32>,
pub bg_offset_y_full_single_screen: Option<F32WithNanInf>,
pub bg_offset_z_full_single_screen: Option<f32>,
pub bg_scale_x_full_single_screen: Option<f32>,
pub bg_scale_y_full_single_screen: Option<f32>,
pub bg_scale_y_full_single_screen: Option<F32WithNanInf>,
pub bg_scale_z_full_single_screen: Option<f32>,
pub bg_view_horizontal_offset_full_single_screen: Option<f32>,
pub bg_view_vertical_offset_full_single_screen: Option<f32>,
Expand Down Expand Up @@ -371,7 +376,7 @@ pub(crate) struct GameDataJson {
pub custom_colors: [ColorJson; 16],
pub protection_data: Option<Vec<u8>>,
//pub code: StringWithEncoding,
pub is_locked: Option<bool>,
pub locked: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_10_8_0_beta1_to_beta4: Option<bool>,
}
Expand Down Expand Up @@ -437,10 +442,10 @@ impl GameDataJson {
bg_layback_full_single_screen: self.bg_layback_full_single_screen,
bg_fov_full_single_screen: self.bg_fov_full_single_screen,
bg_offset_x_full_single_screen: self.bg_offset_x_full_single_screen,
bg_offset_y_full_single_screen: self.bg_offset_y_full_single_screen,
bg_offset_y_full_single_screen: self.bg_offset_y_full_single_screen.map(f32::from),
bg_offset_z_full_single_screen: self.bg_offset_z_full_single_screen,
bg_scale_x_full_single_screen: self.bg_scale_x_full_single_screen,
bg_scale_y_full_single_screen: self.bg_scale_y_full_single_screen,
bg_scale_y_full_single_screen: self.bg_scale_y_full_single_screen.map(f32::from),
bg_scale_z_full_single_screen: self.bg_scale_z_full_single_screen,
bg_view_horizontal_offset_full_single_screen: self
.bg_view_horizontal_offset_full_single_screen,
Expand Down Expand Up @@ -555,7 +560,7 @@ impl GameDataJson {
custom_colors,
protection_data: self.protection_data.clone(),
code: StringWithEncoding::empty(),
is_locked: self.is_locked,
locked: self.locked,
is_10_8_0_beta1_to_beta4: self.is_10_8_0_beta1_to_beta4.unwrap_or(false),
}
}
Expand Down Expand Up @@ -617,10 +622,14 @@ impl GameDataJson {
bg_layback_full_single_screen: game_data.bg_layback_full_single_screen,
bg_fov_full_single_screen: game_data.bg_fov_full_single_screen,
bg_offset_x_full_single_screen: game_data.bg_offset_x_full_single_screen,
bg_offset_y_full_single_screen: game_data.bg_offset_y_full_single_screen,
bg_offset_y_full_single_screen: game_data
.bg_offset_y_full_single_screen
.map(F32WithNanInf::from),
bg_offset_z_full_single_screen: game_data.bg_offset_z_full_single_screen,
bg_scale_x_full_single_screen: game_data.bg_scale_x_full_single_screen,
bg_scale_y_full_single_screen: game_data.bg_scale_y_full_single_screen,
bg_scale_y_full_single_screen: game_data
.bg_scale_y_full_single_screen
.map(F32WithNanInf::from),
bg_scale_z_full_single_screen: game_data.bg_scale_z_full_single_screen,
bg_view_horizontal_offset_full_single_screen: game_data
.bg_view_horizontal_offset_full_single_screen,
Expand Down Expand Up @@ -717,7 +726,7 @@ impl GameDataJson {
custom_colors,
protection_data: game_data.protection_data.clone(),
// code: game_data.code.clone(),
is_locked: game_data.is_locked,
locked: game_data.locked,
is_10_8_0_beta1_to_beta4: Some(game_data.is_10_8_0_beta1_to_beta4)
.filter(|x| x == &true),
}
Expand Down Expand Up @@ -892,7 +901,7 @@ impl Default for GameData {
bg_window_bottom_x_offset_full_single_screen: None,
bg_window_bottom_y_offset_full_single_screen: None,
bg_window_bottom_z_offset_full_single_screen: None,
is_locked: None,
locked: None,
}
}
}
Expand Down Expand Up @@ -1226,8 +1235,8 @@ pub fn write_all_gamedata_records(gamedata: &GameData, version: &Version) -> Vec
writer.write_tagged_data("SECB", protection_data);
}
writer.write_tagged_string_with_encoding_no_size("CODE", &gamedata.code);
if let Some(is_locked) = gamedata.is_locked {
writer.write_tagged_bool("TLCK", is_locked);
if let Some(is_locked) = gamedata.locked {
writer.write_tagged_u32("TLCK", is_locked);
}

writer.close(true);
Expand Down Expand Up @@ -1458,7 +1467,7 @@ pub fn read_all_gamedata_records(input: &[u8], version: &Version) -> GameData {
// at least a the time of 1060, some code was still encoded in latin1
gamedata.code = reader.get_str_with_encoding_no_remaining_update(len as usize);
}
"TLCK" => gamedata.is_locked = Some(reader.get_bool()),
"TLCK" => gamedata.locked = Some(reader.get_u32()),
other => {
let data = reader.get_record_data(false);
println!("unhandled tag {} {} bytes", other, data.len());
Expand Down Expand Up @@ -1658,7 +1667,7 @@ mod tests {
bg_window_bottom_x_offset_full_single_screen: None,
bg_window_bottom_y_offset_full_single_screen: None,
bg_window_bottom_z_offset_full_single_screen: None,
is_locked: Some(true),
locked: Faker.fake(),
is_10_8_0_beta1_to_beta4: false,
};
let version = Version::new(1074);
Expand Down
2 changes: 1 addition & 1 deletion src/vpx/gameitem/gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl Default for Gate {
name: Default::default(),
two_way: false,
is_reflection_enabled: None, //true,
gate_type: Some(GateType::Plate),
gate_type: None, //Some(GateType::Plate),
is_locked: false,
editor_layer: Default::default(),
editor_layer_name: None,
Expand Down
12 changes: 11 additions & 1 deletion src/vpx/sound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ pub(crate) fn read(file_version: &Version, reader: &mut BiffReader) -> SoundData
10
};

// We have seen below case for a 1040 file:
// Legacy behavior, where the BG selection was encoded into the strings directly
// path = "* Backglass Output *" or name contains "bgout_"
// This is still seen as a wav file, even if the path does not end with .wav!

for i in 0..num_values {
match i {
0 => {
Expand Down Expand Up @@ -303,8 +308,13 @@ pub(crate) fn read(file_version: &Version, reader: &mut BiffReader) -> SoundData
}
}

/// Check if the path is a wav file.
/// If the path does not have an extension, it is also considered a wav file!
fn is_wav(path: &str) -> bool {
path.to_lowercase().ends_with(".wav")
match path.rfind('.') {
Some(pos) => path[(pos + 1)..].eq_ignore_ascii_case("wav"),
None => true,
}
}

pub(crate) fn write(file_version: &Version, sound: &SoundData, writer: &mut BiffWriter) {
Expand Down
1 change: 1 addition & 0 deletions tests/vpx_read_extract_assemble_write_compare_all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod test {
// * Inhabiting Mars RC 4 - for animation frame
// * DieHard_272.vpx - primitive "BM_pAirDuctGate" has a NaN value for nx
// * Johnny Mnemonic (Williams 1995) VPW v1.0.2.vpx - animated frames that overlap with primitive names
// * Future Spa (Bally 1979) v4.3.vpx - NaN in table setup values

// TODO why is par_iter() not faster but just consuming all cpu cores?
paths
Expand Down

0 comments on commit 767184b

Please sign in to comment.