From bfa378b6e240c9a2d1716b35917e0132241bcf35 Mon Sep 17 00:00:00 2001 From: ScanMountGoat Date: Sat, 27 Aug 2022 19:40:47 -0500 Subject: [PATCH 1/3] use latest binrw from crates.io --- Cargo.toml | 2 +- src/lib.rs | 40 +++++++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f95c45..6cae51f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ required-features = ["cli"] [dependencies] modular-bitfield = "0.11" -binrw = { git = "https://github.com/jam1garner/binrw", rev = "e8ae07ec" } +binrw = "0.9.2" binwrite = "0.2.1" # serde support diff --git a/src/lib.rs b/src/lib.rs index 9408ee3..23e9314 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,16 +1,26 @@ -use binrw::{prelude::*, punctuated::Punctuated, NullString, derive_binread}; +use binrw::{ + binread, punctuated::Punctuated, BinRead, BinReaderExt, BinResult, NullString, VecArgs, +}; use binwrite::BinWrite; -use std::path::Path; use core::fmt; +use std::path::Path; #[cfg(feature = "serde_support")] -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; mod writer; mod line_flags; pub use line_flags::LineFlags; +pub fn read_punctuated, R: binrw::io::Read + binrw::io::Seek>( + reader: &mut R, + options: &binrw::ReadOptions, + args: VecArgs<()>, +) -> BinResult> { + Punctuated::::separated(reader, options, args).map(Punctuated::into_values) +} + #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] #[derive(BinRead, Debug)] #[br(big, magic = b"\x00\x00\x00\x01\x0D\x01\x4C\x56\x44\x31")] @@ -37,7 +47,7 @@ pub struct LvdFile { pub unk6: UnsupportedSection, pub unk7: UnsupportedSection, pub shrunken_camera_boundary: Section, // version 13 only - pub shrunken_blast_zone: Section, // version 13 only + pub shrunken_blast_zone: Section, // version 13 only } #[derive(BinRead, Debug)] @@ -60,7 +70,7 @@ pub struct LvdEntry { pub bone_name: String, } -#[derive_binread] +#[binread] #[derive(Debug)] #[br(magic = b"\x04\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] @@ -69,11 +79,11 @@ pub struct Collision { pub col_flags: ColFlags, #[br(temp, pad_before = 1)] pub vertex_count: u32, - #[br(pad_before = 1, parse_with = Punctuated::::separated, map = Punctuated::into_values, count = vertex_count)] + #[br(pad_before = 1, parse_with = read_punctuated, count = vertex_count)] pub vertices: Vec, #[br(temp, pad_before = 1)] pub normal_count: u32, - #[br(pad_before = 1, parse_with = Punctuated::::separated, map = Punctuated::into_values, count = normal_count)] + #[br(pad_before = 1, parse_with = read_punctuated, count = normal_count)] pub normals: Vec, #[br(temp, pad_before = 1)] pub cliff_count: u32, @@ -81,7 +91,7 @@ pub struct Collision { pub cliffs: Vec, #[br(temp, pad_before = 1)] pub line_count: u32, - #[br(pad_before = 1, parse_with = Punctuated::::separated, map = Punctuated::into_values, count = line_count)] + #[br(pad_before = 1, parse_with = read_punctuated, count = line_count)] pub materials: Vec, #[br(temp, pad_before = 1)] pub unk_count: u32, @@ -215,7 +225,7 @@ pub struct Bounds { pub bottom: f32, } -#[derive_binread] +#[binread] #[derive(Debug)] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] #[br(magic = b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")] @@ -226,11 +236,11 @@ pub struct ItemSpawner { pub unk: u8, #[br(temp, pad_before = 1)] pub section_count: u32, - #[br(pad_before = 1, parse_with = Punctuated::::separated, map = Punctuated::into_values, count = section_count)] + #[br(pad_before = 1, parse_with = read_punctuated, count = section_count)] pub sections: Vec, } -#[derive_binread] +#[binread] #[derive(Debug)] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] #[br(magic = b"\x04\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")] @@ -242,7 +252,7 @@ pub struct PokemonTrainerRange { pub boundary_max: Vector3, #[br(temp, pad_before = 1)] pub trainer_count: u32, - #[br(pad_before = 1, parse_with = Punctuated::::separated, map = Punctuated::into_values, count = trainer_count)] + #[br(pad_before = 1, parse_with = read_punctuated, count = trainer_count)] pub trainers: Vec, #[br(pad_before = 1, pad_size_to = 0x40, map = NullString::into_string)] pub platform_name: String, @@ -272,7 +282,7 @@ pub struct Point { pub pos: Vector3, } -#[derive_binread] +#[binread] #[derive(Debug)] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] pub enum LvdShape { @@ -310,7 +320,7 @@ pub enum LvdShape { Path { #[br(temp, pad_before = 0x12)] point_count: u32, - #[br(pad_before = 1, parse_with = Punctuated::::separated, map = Punctuated::into_values, count = point_count)] + #[br(pad_before = 1, parse_with = read_punctuated, count = point_count)] points: Vec, }, Invalid { @@ -326,7 +336,7 @@ pub struct UnsupportedSection { pub count: u32, } -#[derive_binread] +#[binread] #[derive(Debug)] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde_support", serde(transparent))] From b95904802b502bd0a7d161142d3a4d58b3c0b188 Mon Sep 17 00:00:00 2001 From: ScanMountGoat Date: Sat, 27 Aug 2022 22:40:45 -0500 Subject: [PATCH 2/3] fix read/write for ultimate lvds --- src/lib.rs | 37 +++++++++--- src/writer.rs | 162 +++++++++++++++++++++++++++++--------------------- 2 files changed, 123 insertions(+), 76 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 23e9314..10d4d12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ pub fn read_punctuated, R: binrw::io::Read + binrw::io::Se #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] #[derive(BinRead, Debug)] -#[br(big, magic = b"\x00\x00\x00\x01\x0D\x01\x4C\x56\x44\x31")] +#[br(big, magic = b"\x00\x00\x00\x01\x0D\x01LVD\x31")] pub struct LvdFile { pub collisions: Section, pub spawns: Section, @@ -36,11 +36,11 @@ pub struct LvdFile { pub unk3: UnsupportedSection, pub fs_area_cam: UnsupportedSection, pub fs_cam_limit: UnsupportedSection, - pub damage_shapes: UnsupportedSection, + pub damage_shapes: Section, pub item_spawners: Section, pub ptrainer_ranges: Section, // version 13 only pub ptrainer_platforms: Section, // version 13 only - pub general_shapes: UnsupportedSection, + pub general_shapes: Section, pub general_points: Section, pub unk4: UnsupportedSection, pub unk5: UnsupportedSection, @@ -191,6 +191,27 @@ pub enum GroundCollAttr { GROUND_COLL_ATTR_JACK_MEMENTOES = 43, } +#[derive(BinRead, Debug)] +#[br(magic = b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct DamageShape { + pub entry: LvdEntry, + #[br(pad_before = 1)] + pub unk1: u32, + #[br(pad_after = 1)] + pub unk2: [f32; 8], +} + +#[derive(BinRead, Debug)] +#[br(magic = b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct GeneralShape { + pub entry: LvdEntry, + #[br(pad_before = 1)] + pub unk1: u32, + pub shape: LvdShape, +} + #[derive(BinRead, Debug)] #[br(magic = b"\x02\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] @@ -236,7 +257,7 @@ pub struct ItemSpawner { pub unk: u8, #[br(temp, pad_before = 1)] pub section_count: u32, - #[br(pad_before = 1, parse_with = read_punctuated, count = section_count)] + #[br(pad_before = if section_count > 0 { 1 } else {0 }, parse_with = read_punctuated, count = section_count)] pub sections: Vec, } @@ -252,7 +273,7 @@ pub struct PokemonTrainerRange { pub boundary_max: Vector3, #[br(temp, pad_before = 1)] pub trainer_count: u32, - #[br(pad_before = 1, parse_with = read_punctuated, count = trainer_count)] + #[br(pad_before = if trainer_count > 0 { 1 } else { 0 }, parse_with = read_punctuated, count = trainer_count)] pub trainers: Vec, #[br(pad_before = 1, pad_size_to = 0x40, map = NullString::into_string)] pub platform_name: String, @@ -292,7 +313,7 @@ pub enum LvdShape { y: f32, #[br(temp, pad_before = 8)] unk: u8, - #[br(temp)] + #[br(temp, pad_before = 1)] point_count: u32, }, #[br(magic = b"\x03\0\0\0\x02")] @@ -302,7 +323,7 @@ pub enum LvdShape { radius: f32, #[br(temp, pad_before = 4)] unk: u8, - #[br(temp)] + #[br(temp, pad_after = 1)] point_count: u32, }, #[br(magic = b"\x03\0\0\0\x03")] @@ -313,7 +334,7 @@ pub enum LvdShape { top: f32, #[br(temp)] unk: u8, - #[br(temp)] + #[br(temp, pad_before = 1)] point_count: u32, }, #[br(magic = b"\x03\0\0\0\x04")] diff --git a/src/writer.rs b/src/writer.rs index 5d006af..7d8c77e 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,6 +1,6 @@ use crate::*; +use std::io::{self, BufWriter, Write}; use std::path::Path; -use std::io::{self, Write, BufWriter}; use binwrite::{BinWrite, WriterOption}; @@ -9,7 +9,7 @@ impl LvdFile { pub fn save>(&self, path: P) -> io::Result<()> { let mut file = BufWriter::new(std::fs::File::create(path.as_ref())?); - + self.write(&mut file) } @@ -21,40 +21,29 @@ impl LvdFile { &self.respawns, &self.camera_boundary, &self.blast_zone, - - ( - &self.enemy_generators, - &self.unk1, - &self.unk2, - &self.unk3, - ), + (&self.enemy_generators, &self.unk1, &self.unk2, &self.unk3), &self.fs_area_cam, - &self.fs_cam_limit, + &self.fs_cam_limit, &self.damage_shapes, &self.item_spawners, &self.ptrainer_ranges, &self.ptrainer_platforms, &self.general_shapes, &self.general_points, - ( - &self.unk4, - &self.unk5, - &self.unk6, - &self.unk7, - ), + (&self.unk4, &self.unk5, &self.unk6, &self.unk7), &self.shrunken_camera_boundary, &self.shrunken_blast_zone, - ).write_options(writer, &binwrite::writer_option_new!(endian: binwrite::Endian::Big)) + ) + .write_options( + writer, + &binwrite::writer_option_new!(endian: binwrite::Endian::Big), + ) } } impl> BinWrite for Section { fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { - ( - 1u8, - self.data.len() as u32, - &self.data - ).write_options(writer, options) + (1u8, self.data.len() as u32, &self.data).write_options(writer, options) } } @@ -84,11 +73,7 @@ impl<'a, T: BinWrite> BinWrite for LvdList<'a, T> { impl BinWrite for CollisionMaterial { fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { - ( - self.line_material as u32, - 0u32, - &self.line_flags, - ).write_options(writer, options) + (self.line_material as u32, 0u32, &self.line_flags).write_options(writer, options) } } @@ -118,7 +103,8 @@ impl BinWrite for Collision { 1u8, self.unknowns.len() as u32, &self.unknowns, - ).write_options(writer, options) + ) + .write_options(writer, options) } } @@ -131,7 +117,8 @@ impl BinWrite for CollisionCliff { &self.pos, &self.angle, &self.line_index, - ).write_options(writer, options) + ) + .write_options(writer, options) } } @@ -146,14 +133,15 @@ impl BinWrite for UnknownEntry { &self.unk2, &self.unk3, &self.unk4, - ).write_options(writer, options) + ) + .write_options(writer, options) } } #[derive(BinWrite)] struct String38<'a> { #[binwrite(cstr, align_after(0x38))] - s: &'a str + s: &'a str, } fn string38(s: &str) -> String38 { @@ -163,7 +151,7 @@ fn string38(s: &str) -> String38 { #[derive(BinWrite)] struct String40<'a> { #[binwrite(cstr, align_after(0x40))] - s: &'a str + s: &'a str, } fn string40(s: &str) -> String40 { @@ -171,7 +159,11 @@ fn string40(s: &str) -> String40 { } pub(crate) fn c_bool(&x: &bool) -> u8 { - if x { 1 } else { 0 } + if x { + 1 + } else { + 0 + } } impl BinWrite for LvdEntry { @@ -191,7 +183,8 @@ impl BinWrite for LvdEntry { self.unk3, 1u8, string40(&self.bone_name), - ).write_options(writer, options) + ) + .write_options(writer, options) } } @@ -202,7 +195,8 @@ impl BinWrite for Spawn { &self.entry, 1u8, &self.pos, - ).write_options(writer, options) + ) + .write_options(writer, options) } } @@ -216,7 +210,8 @@ impl BinWrite for Bounds { self.right, self.top, self.bottom, - ).write_options(writer, options) + ) + .write_options(writer, options) } } @@ -230,41 +225,34 @@ impl BinWrite for ItemSpawner { self.unk, 1u8, self.sections.len() as u32, - 1u8, - LvdList(&self.sections), - ).write_options(writer, options) + ) + .write_options(writer, options)?; + + if self.sections.len() > 0 { + 1u8.write_options(writer, options)?; + } + + LvdList(&self.sections).write_options(writer, options) } } impl BinWrite for LvdShape { fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { match self { - Self::Point { x, y } => ( - b"\x03\0\0\0\x01", - x, - y, - [0u8; 8], - 0u8, - 0u32 - ).write_options(writer, options), - Self::Circle { x, y, radius } => ( - b"\x03\0\0\0\x02", - x, - y, - radius, - [0u8; 4], - 0u8, - 0u32 - ).write_options(writer, options), - Self::Rectangle { left, right, bottom, top } => ( - b"\x03\0\0\0\x03", + Self::Point { x, y } => { + (b"\x03\0\0\0\x01", x, y, [0u8; 8], 1u8, 1u8, 0u32).write_options(writer, options) + } + Self::Circle { x, y, radius } => { + (b"\x03\0\0\0\x02", x, y, radius, [0u8; 4], 1u8, 1u8, 0u32) + .write_options(writer, options) + } + Self::Rectangle { left, right, bottom, top, - 0u8, - 0u32 - ).write_options(writer, options), + } => (b"\x03\0\0\0\x03", left, right, bottom, top, 1u8, 1u8, 0u32) + .write_options(writer, options), Self::Path { points } => ( b"\x03\0\0\0\x04", [0u8; 0x10], @@ -273,8 +261,9 @@ impl BinWrite for LvdShape { points.len() as u32, 1u8, LvdList(points), - ).write_options(writer, options), - _ => unreachable!() + ) + .write_options(writer, options), + _ => unreachable!(), } } } @@ -290,13 +279,21 @@ impl BinWrite for PokemonTrainerRange { &self.boundary_max, 1u8, self.trainers.len() as u32, - 1u8, + ) + .write_options(writer, options)?; + + if self.trainers.len() > 0 { + 1u8.write_options(writer, options)?; + } + + ( LvdList(&self.trainers), 1u8, string40(&self.platform_name), 1u8, string40(&self.sub_name), - ).write_options(writer, options) + ) + .write_options(writer, options) } } @@ -306,8 +303,9 @@ impl BinWrite for PokemonTrainerPlatform { b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, 1u8, - &self.pos - ).write_options(writer, options) + &self.pos, + ) + .write_options(writer, options) } } @@ -322,7 +320,35 @@ impl BinWrite for Point { self.ty, &self.pos, [0u8; 0x10], - ).write_options(writer, options) + ) + .write_options(writer, options) + } +} + +impl BinWrite for DamageShape { + fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + (( + b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", + &self.entry, + 1u8, + self.unk1, + self.unk2, + 0u8, + )) + .write_options(writer, options) + } +} + +impl BinWrite for GeneralShape { + fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + (( + b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", + &self.entry, + 1u8, + self.unk1, + &self.shape, + )) + .write_options(writer, options) } } From b074b02d3e4dd53415b4e67d5d598003be4207a2 Mon Sep 17 00:00:00 2001 From: ScanMountGoat Date: Sun, 28 Aug 2022 15:02:41 -0500 Subject: [PATCH 3/3] use binrw instead of binwrite --- Cargo.toml | 1 - src/lib.rs | 16 ++- src/line_flags.rs | 90 ++++++++-------- src/main.rs | 6 +- src/writer.rs | 255 ++++++++++++++++++++++++++++++++++------------ 5 files changed, 248 insertions(+), 120 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6cae51f..f47c489 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ required-features = ["cli"] [dependencies] modular-bitfield = "0.11" binrw = "0.9.2" -binwrite = "0.2.1" # serde support serde = { version = "1", features = ["derive"], optional = true } diff --git a/src/lib.rs b/src/lib.rs index 10d4d12..a0a99cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,7 @@ -use binrw::{ - binread, punctuated::Punctuated, BinRead, BinReaderExt, BinResult, NullString, VecArgs, -}; -use binwrite::BinWrite; +use binrw::{binread, prelude::*, punctuated::Punctuated, NullString, VecArgs}; use core::fmt; use std::path::Path; +use writer::c_bool; #[cfg(feature = "serde_support")] use serde::{Deserialize, Serialize}; @@ -99,25 +97,23 @@ pub struct Collision { pub unknowns: Vec, } -use writer::c_bool as to_c_bool; - #[derive(BinRead, BinWrite, Debug)] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] pub struct ColFlags { #[br(map = cbool)] - #[binwrite(preprocessor(to_c_bool))] + #[binwrite(map(c_bool))] pub flag1: bool, #[br(map = cbool)] - #[binwrite(preprocessor(to_c_bool))] + #[binwrite(map(c_bool))] pub rig_col: bool, #[br(map = cbool)] - #[binwrite(preprocessor(to_c_bool))] + #[binwrite(map(c_bool))] pub flag3: bool, #[br(map = cbool)] - #[binwrite(preprocessor(to_c_bool))] + #[binwrite(map(c_bool))] pub drop_through: bool, } diff --git a/src/line_flags.rs b/src/line_flags.rs index 559de8f..4d74ad7 100644 --- a/src/line_flags.rs +++ b/src/line_flags.rs @@ -1,11 +1,11 @@ -use modular_bitfield::prelude::*; -use binwrite::{BinWrite, WriterOption}; use binrw::BinRead; +use binrw::{BinWrite, WriteOptions}; +use modular_bitfield::prelude::*; -use std::io::{Write, self}; +use std::io::Write; #[cfg(feature = "serde_support")] -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; fn from_bytes(mut x: [u8; 4]) -> LineFlags { x.reverse(); @@ -15,9 +15,10 @@ fn from_bytes(mut x: [u8; 4]) -> LineFlags { #[bitfield] #[derive(BinRead, Debug, Clone, Copy)] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde_support", serde( - from = "LineFlagsSerde", into = "LineFlagsSerde" -))] +#[cfg_attr( + feature = "serde_support", + serde(from = "LineFlagsSerde", into = "LineFlagsSerde") +)] #[br(map = from_bytes)] pub struct LineFlags { pub length_zero: bool, @@ -55,10 +56,17 @@ pub struct LineFlags { } impl BinWrite for LineFlags { - fn write_options(&self, writer: &mut W, _: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + _: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { let mut bytes = self.into_bytes(); bytes.reverse(); - writer.write_all(&bytes) + writer.write_all(&bytes).map_err(Into::into) } } @@ -103,38 +111,38 @@ struct LineFlagsSerde { impl From for LineFlags { fn from(lfs: LineFlagsSerde) -> Self { LineFlags::new() - .with_length_zero(lfs.length_zero) - .with_pacman_final_ignore(lfs.pacman_final_ignore) - .with_fall(lfs.fall) - .with_ignore_ray_check(lfs.ignore_ray_check) - .with_dive(lfs.dive) - .with_unpaintable(lfs.unpaintable) - .with_item(lfs.item) - .with_ignore_fighter_other(lfs.ignore_fighter_other) - .with_right(lfs.right) - .with_left(lfs.left) - .with_upper(lfs.upper) - .with_under(lfs.under) - .with_not_attach(lfs.not_attach) - .with_throughable(lfs.throughable) - .with_hang_l(lfs.hang_l) - .with_hang_r(lfs.hang_r) - .with_ignore_link_from_left(lfs.ignore_link_from_left) - .with_cloud(lfs.cloud) - .with_ignore_link_from_right(lfs.ignore_link_from_right) - .with_not_expand_near_search(lfs.not_expand_near_search) - .with_ignore(lfs.ignore) - .with_breakable(lfs.breakable) - .with_immediate_relanding_ban(lfs.immediate_relanding_ban) - .with_ignore_line_type1(lfs.ignore_line_type1) - .with_pickel_block(lfs.pickel_block) - .with_deceleration(lfs.deceleration) - .with_virtual_hit_line_up(lfs.virtual_hit_line_up) - .with_virtual_hit_line_left(lfs.virtual_hit_line_left) - .with_virtual_hit_line_right(lfs.virtual_hit_line_right) - .with_virtual_hit_line_down(lfs.virtual_hit_line_down) - .with_virtual_wall_hit_line(lfs.virtual_wall_hit_line) - .with_ignore_boss(lfs.ignore_boss) + .with_length_zero(lfs.length_zero) + .with_pacman_final_ignore(lfs.pacman_final_ignore) + .with_fall(lfs.fall) + .with_ignore_ray_check(lfs.ignore_ray_check) + .with_dive(lfs.dive) + .with_unpaintable(lfs.unpaintable) + .with_item(lfs.item) + .with_ignore_fighter_other(lfs.ignore_fighter_other) + .with_right(lfs.right) + .with_left(lfs.left) + .with_upper(lfs.upper) + .with_under(lfs.under) + .with_not_attach(lfs.not_attach) + .with_throughable(lfs.throughable) + .with_hang_l(lfs.hang_l) + .with_hang_r(lfs.hang_r) + .with_ignore_link_from_left(lfs.ignore_link_from_left) + .with_cloud(lfs.cloud) + .with_ignore_link_from_right(lfs.ignore_link_from_right) + .with_not_expand_near_search(lfs.not_expand_near_search) + .with_ignore(lfs.ignore) + .with_breakable(lfs.breakable) + .with_immediate_relanding_ban(lfs.immediate_relanding_ban) + .with_ignore_line_type1(lfs.ignore_line_type1) + .with_pickel_block(lfs.pickel_block) + .with_deceleration(lfs.deceleration) + .with_virtual_hit_line_up(lfs.virtual_hit_line_up) + .with_virtual_hit_line_left(lfs.virtual_hit_line_left) + .with_virtual_hit_line_right(lfs.virtual_hit_line_right) + .with_virtual_hit_line_down(lfs.virtual_hit_line_down) + .with_virtual_wall_hit_line(lfs.virtual_wall_hit_line) + .with_ignore_boss(lfs.ignore_boss) } } diff --git a/src/main.rs b/src/main.rs index 4c7701b..2c210f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ -use std::path::PathBuf; use std::fs; +use std::path::PathBuf; -use lvd::LvdFile; use clap::Parser; +use lvd::LvdFile; #[derive(Parser)] struct Args { @@ -17,7 +17,7 @@ fn main() { match out_file.extension().map(|x| x.to_str()).flatten() { Some("lvd") => out_file.set_extension("yaml"), Some("yaml") | Some("yml") => out_file.set_extension("lvd"), - _ => true + _ => true, }; out_file }); diff --git a/src/writer.rs b/src/writer.rs index 7d8c77e..49d928f 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,19 +1,19 @@ use crate::*; -use std::io::{self, BufWriter, Write}; +use std::io::{BufWriter, Seek, Write}; use std::path::Path; -use binwrite::{BinWrite, WriterOption}; +use binrw::{BinWrite, WriteOptions}; impl LvdFile { const MAGIC: &'static [u8] = b"\x00\x00\x00\x01\x0D\x01\x4C\x56\x44\x31"; - pub fn save>(&self, path: P) -> io::Result<()> { + pub fn save>(&self, path: P) -> Result<(), binrw::Error> { let mut file = BufWriter::new(std::fs::File::create(path.as_ref())?); self.write(&mut file) } - pub fn write(&self, writer: &mut W) -> io::Result<()> { + pub fn write(&self, writer: &mut W) -> Result<(), binrw::Error> { ( Self::MAGIC, &self.collisions, @@ -34,36 +34,54 @@ impl LvdFile { &self.shrunken_camera_boundary, &self.shrunken_blast_zone, ) - .write_options( - writer, - &binwrite::writer_option_new!(endian: binwrite::Endian::Big), - ) + .write_options(writer, &binrw::WriteOptions::new(binrw::Endian::Big), ()) } } -impl> BinWrite for Section { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { - (1u8, self.data.len() as u32, &self.data).write_options(writer, options) +impl + BinRead> BinWrite for Section { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { + (1u8, self.data.len() as u32, &self.data).write_options(writer, options, ()) } } impl BinWrite for UnsupportedSection { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { - (1u8, 0u32).write_options(writer, options) + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { + (1u8, 0u32).write_options(writer, options, ()) } } struct LvdList<'a, T>(&'a Vec); -impl<'a, T: BinWrite> BinWrite for LvdList<'a, T> { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { +impl<'a, T: BinWrite> BinWrite for LvdList<'a, T> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { let mut iter = self.0.iter(); if let Some(first) = iter.next() { - first.write_options(writer, options)?; + first.write_options(writer, options, ())?; for item in iter { - 1u8.write_options(writer, options)?; - item.write_options(writer, options)?; + 1u8.write_options(writer, options, ())?; + item.write_options(writer, options, ())?; } } @@ -72,13 +90,27 @@ impl<'a, T: BinWrite> BinWrite for LvdList<'a, T> { } impl BinWrite for CollisionMaterial { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { - (self.line_material as u32, 0u32, &self.line_flags).write_options(writer, options) + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { + (self.line_material as u32, 0u32, &self.line_flags).write_options(writer, options, ()) } } impl BinWrite for Collision { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( ( b"\x04\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", @@ -104,12 +136,19 @@ impl BinWrite for Collision { self.unknowns.len() as u32, &self.unknowns, ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for CollisionCliff { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x03\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, @@ -118,12 +157,19 @@ impl BinWrite for CollisionCliff { &self.angle, &self.line_index, ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for UnknownEntry { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x02\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, @@ -134,13 +180,13 @@ impl BinWrite for UnknownEntry { &self.unk3, &self.unk4, ) - .write_options(writer, options) + .write_options(writer, options, ()) } } #[derive(BinWrite)] struct String38<'a> { - #[binwrite(cstr, align_after(0x38))] + #[bw(map(cstr), pad_size_to(0x38))] s: &'a str, } @@ -150,7 +196,7 @@ fn string38(s: &str) -> String38 { #[derive(BinWrite)] struct String40<'a> { - #[binwrite(cstr, align_after(0x40))] + #[bw(map(cstr), pad_size_to(0x40))] s: &'a str, } @@ -158,6 +204,10 @@ fn string40(s: &str) -> String40 { String40 { s } } +fn cstr(s: &&str) -> Vec { + s.bytes().chain(std::iter::once(0u8)).collect() +} + pub(crate) fn c_bool(&x: &bool) -> u8 { if x { 1 @@ -167,7 +217,14 @@ pub(crate) fn c_bool(&x: &bool) -> u8 { } impl BinWrite for LvdEntry { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( 1u8, string38(&self.name), @@ -184,24 +241,38 @@ impl BinWrite for LvdEntry { 1u8, string40(&self.bone_name), ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for Spawn { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x02\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, 1u8, &self.pos, ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for Bounds { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x02\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, @@ -211,12 +282,19 @@ impl BinWrite for Bounds { self.top, self.bottom, ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for ItemSpawner { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, @@ -226,33 +304,45 @@ impl BinWrite for ItemSpawner { 1u8, self.sections.len() as u32, ) - .write_options(writer, options)?; + .write_options(writer, options, ())?; - if self.sections.len() > 0 { - 1u8.write_options(writer, options)?; + if !self.sections.is_empty() { + 1u8.write_options(writer, options, ())?; } - LvdList(&self.sections).write_options(writer, options) + LvdList(&self.sections).write_options(writer, options, ()) } } impl BinWrite for LvdShape { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { match self { - Self::Point { x, y } => { - (b"\x03\0\0\0\x01", x, y, [0u8; 8], 1u8, 1u8, 0u32).write_options(writer, options) - } + Self::Point { x, y } => (b"\x03\0\0\0\x01", x, y, [0u8; 8], 1u8, 1u8, 0u32) + .write_options(writer, options, ()), Self::Circle { x, y, radius } => { - (b"\x03\0\0\0\x02", x, y, radius, [0u8; 4], 1u8, 1u8, 0u32) - .write_options(writer, options) + (b"\x03\0\0\0\x02", x, y, radius, [0u8; 4], 1u8, 1u8, 0u32).write_options( + writer, + options, + (), + ) } Self::Rectangle { left, right, bottom, top, - } => (b"\x03\0\0\0\x03", left, right, bottom, top, 1u8, 1u8, 0u32) - .write_options(writer, options), + } => (b"\x03\0\0\0\x03", left, right, bottom, top, 1u8, 1u8, 0u32).write_options( + writer, + options, + (), + ), Self::Path { points } => ( b"\x03\0\0\0\x04", [0u8; 0x10], @@ -262,14 +352,21 @@ impl BinWrite for LvdShape { 1u8, LvdList(points), ) - .write_options(writer, options), + .write_options(writer, options, ()), _ => unreachable!(), } } } impl BinWrite for PokemonTrainerRange { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x04\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, @@ -280,10 +377,10 @@ impl BinWrite for PokemonTrainerRange { 1u8, self.trainers.len() as u32, ) - .write_options(writer, options)?; + .write_options(writer, options, ())?; - if self.trainers.len() > 0 { - 1u8.write_options(writer, options)?; + if !self.trainers.is_empty() { + 1u8.write_options(writer, options, ())?; } ( @@ -293,24 +390,38 @@ impl BinWrite for PokemonTrainerRange { 1u8, string40(&self.sub_name), ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for PokemonTrainerPlatform { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, 1u8, &self.pos, ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for Point { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { ( b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, @@ -321,34 +432,48 @@ impl BinWrite for Point { &self.pos, [0u8; 0x10], ) - .write_options(writer, options) + .write_options(writer, options, ()) } } impl BinWrite for DamageShape { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { - (( + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { + ( b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, 1u8, self.unk1, self.unk2, 0u8, - )) - .write_options(writer, options) + ) + .write_options(writer, options, ()) } } impl BinWrite for GeneralShape { - fn write_options(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> { - (( + type Args = (); + + fn write_options( + &self, + writer: &mut W, + options: &WriteOptions, + _: Self::Args, + ) -> Result<(), binrw::Error> { + ( b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02", &self.entry, 1u8, self.unk1, &self.shape, - )) - .write_options(writer, options) + ) + .write_options(writer, options, ()) } }