Skip to content

Commit

Permalink
Merge pull request #1 from jam1garner/binrw
Browse files Browse the repository at this point in the history
Switch to `binrw`
  • Loading branch information
jam1garner authored Nov 30, 2020
2 parents bc541c9 + 17ca869 commit 68d4f6e
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 38 deletions.
18 changes: 17 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ edition = "2018"
name = "lvd"
path = "src/lib.rs"

[[bin]]
name = "yamlvd"
path = "src/main.rs"
required-features = ["cli"]

[dependencies]
binread = "1.4"
binrw = { git = "https://github.com/jam1garner/binrw" }
binwrite = "0.2.1"

# serde support
serde = { version = "1", features = ["derive"], optional = true }

# cli
clap = { version = "3.0.0-beta", optional = true }
serde_yaml = { version = "0.8", optional = true }

[features]
serde_support = ["serde"]
cli = ["serde_support", "clap", "serde_yaml"]
71 changes: 46 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use binread::{prelude::*, punctuated::Punctuated, NullString, derive_binread};
use binrw::{prelude::*, helpers::Punctuated, NullString, derive_binread};
use binwrite::BinWrite;
use std::path::Path;
use core::fmt;

#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};

mod writer;

#[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")]
pub struct LvdFile {
Expand Down Expand Up @@ -33,6 +37,7 @@ pub struct LvdFile {
pub shrunk_blastzones: Section<Bounds>,
}

#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
#[derive(BinRead, Debug)]
#[br(magic = b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")]
pub struct Point {
Expand All @@ -45,6 +50,7 @@ pub struct Point {
pub pos: Vector3,
}

#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
#[derive(BinRead, Debug)]
#[br(magic = b"\x01\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")]
pub struct PokemonTrainerPlatform {
Expand All @@ -55,6 +61,7 @@ pub struct PokemonTrainerPlatform {

#[derive_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")]
pub struct PokemonTrainer {
pub entry: LvdEntry,
Expand All @@ -64,16 +71,17 @@ pub struct PokemonTrainer {
pub boundary_max: Vector3,
#[br(temp, pad_before = 1)]
pub trainer_count: u32,
#[br(pad_before = 1, parse_with = Punctuated::separated, count = trainer_count)]
pub trainers: Punctuated<Vector3, u8>,
#[br(pad_before = 1, pad_size_to = 0x40)]
pub platform_name: NullString,
#[br(pad_before = 1, pad_size_to = 0x40)]
pub sub_name: NullString,
#[br(pad_before = 1, parse_with = Punctuated::<Vector3, u8>::separated, map = Punctuated::into_values, count = trainer_count)]
pub trainers: Vec<Vector3>,
#[br(pad_before = 1, pad_size_to = 0x40, map = NullString::into_string)]
pub platform_name: String,
#[br(pad_before = 1, pad_size_to = 0x40, map = NullString::into_string)]
pub sub_name: String,
}

#[derive_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")]
pub struct ItemSpawner {
pub entry: LvdEntry,
Expand All @@ -82,12 +90,13 @@ pub struct ItemSpawner {
pub unk: u8,
#[br(temp, pad_before = 1)]
pub section_count: u32,
#[br(pad_before = 1, parse_with = Punctuated::separated, count = section_count)]
pub sections: Punctuated<LvdShape, u8>,
#[br(pad_before = 1, parse_with = Punctuated::<LvdShape, u8>::separated, map = Punctuated::into_values, count = section_count)]
pub sections: Vec<LvdShape>,
}

#[derive_binread]
#[derive(Debug)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub enum LvdShape {
#[br(magic = b"\x03\0\0\0\x01")]
Point {
Expand Down Expand Up @@ -123,8 +132,8 @@ pub enum LvdShape {
Path {
#[br(temp, pad_before = 0x12)]
point_count: u32,
#[br(pad_before = 1, parse_with = Punctuated::separated, count = point_count)]
points: Punctuated<Vector2, u8>,
#[br(pad_before = 1, parse_with = Punctuated::<Vector2, u8>::separated, map = Punctuated::into_values, count = point_count)]
points: Vec<Vector2>,
},
Invalid {
magic: u32,
Expand All @@ -133,13 +142,16 @@ pub enum LvdShape {

#[derive(BinRead, Debug)]
#[br(assert(count == 0))]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct UnsupportedSection {
#[br(pad_before = 1)]
pub count: u32,
}

#[derive_binread]
#[derive(Debug)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde_support", serde(transparent))]
pub struct Section<T: BinRead<Args = ()>> {
#[br(temp, pad_before = 1)]
pub count: u32,
Expand All @@ -164,6 +176,7 @@ impl<T: BinRead<Args = ()>> core::ops::DerefMut for Section<T> {

#[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))]
pub struct Spawn {
pub entry: LvdEntry,
#[br(pad_before = 1)]
Expand All @@ -172,6 +185,7 @@ pub struct Spawn {

#[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))]
pub struct Bounds {
pub entry: LvdEntry,
#[br(pad_before = 1)]
Expand All @@ -182,6 +196,7 @@ pub struct Bounds {
}

#[derive(BinRead, BinWrite)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct Vector3 {
pub x: f32,
pub y: f32,
Expand All @@ -199,6 +214,7 @@ impl fmt::Debug for Vector3 {
}

#[derive(BinRead, BinWrite)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct Vector2 {
pub x: f32,
pub y: f32,
Expand All @@ -215,11 +231,12 @@ fn cbool(x: u8) -> bool {
}

#[derive(BinRead, Debug)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct LvdEntry {
#[br(pad_before = 1, pad_size_to = 0x38)]
pub name: NullString,
#[br(pad_before = 1, pad_size_to = 0x40)]
pub subname: NullString,
#[br(pad_before = 1, pad_size_to = 0x38, map = NullString::into_string)]
pub name: String,
#[br(pad_before = 1, pad_size_to = 0x40, map = NullString::into_string)]
pub subname: String,
#[br(pad_before = 1)]
pub start_pos: Vector3,
#[br(map = cbool)]
Expand All @@ -229,13 +246,14 @@ pub struct LvdEntry {
#[br(pad_before = 1)]
pub unk2: Vector3,
pub unk3: u32,
#[br(pad_before = 1, pad_size_to = 0x40)]
pub bone_name: NullString,
#[br(pad_before = 1, pad_size_to = 0x40, map = NullString::into_string)]
pub bone_name: String,
}

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))]
Expand All @@ -258,11 +276,12 @@ type Material = [u8; 0xC];

#[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))]
pub struct UnknownEntry {
pub entry: LvdEntry,
pub unk: u32,
#[br(pad_before = 1, pad_size_to = 0x40)]
pub string: NullString,
#[br(pad_before = 1, pad_size_to = 0x40, map = NullString::into_string)]
pub string: String,
pub unk2: Vector2,
pub unk3: Vector2,
pub unk4: [u8; 8],
Expand All @@ -271,25 +290,26 @@ pub struct UnknownEntry {
#[derive_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))]
pub struct Collision {
pub entry: LvdEntry,
pub col_flags: ColFlags,
#[br(temp, pad_before = 1)]
pub vert_count: u32,
#[br(pad_before = 1, parse_with = Punctuated::separated, count = vert_count)]
pub verts: Punctuated<Vector2, u8>,
#[br(pad_before = 1, parse_with = Punctuated::<Vector2, u8>::separated, map = Punctuated::into_values, count = vert_count)]
pub verts: Vec<Vector2>,
#[br(temp, pad_before = 1)]
pub normal_count: u32,
#[br(pad_before = 1, parse_with = Punctuated::separated, count = normal_count)]
pub normals: Punctuated<Vector2, u8>,
#[br(pad_before = 1, parse_with = Punctuated::<Vector2, u8>::separated, map = Punctuated::into_values, count = normal_count)]
pub normals: Vec<Vector2>,
#[br(temp, pad_before = 1)]
pub cliff_count: u32,
#[br(count = cliff_count)]
pub cliffs: Vec<CollisionCliff>,
#[br(temp, pad_before = 1)]
pub mat_count: u32,
#[br(pad_before = 1, parse_with = Punctuated::separated, count = mat_count)]
pub materials: Punctuated<Material, u8>,
#[br(pad_before = 1, parse_with = Punctuated::<Material, u8>::separated, map = Punctuated::into_values, count = mat_count)]
pub materials: Vec<Material>,
#[br(temp, pad_before = 1)]
pub unk_count: u32,
#[br(count = unk_count)]
Expand All @@ -298,6 +318,7 @@ pub struct Collision {

#[derive(BinRead, Debug)]
#[br(magic = b"\x03\x04\x01\x01\x77\x35\xBB\x75\x00\x00\x00\x02")]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct CollisionCliff {
pub entry: LvdEntry,
#[br(pad_before = 1)]
Expand Down
31 changes: 31 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::path::PathBuf;
use std::fs;

use lvd::LvdFile;
use clap::Clap;

#[derive(Clap)]
struct Args {
in_file: PathBuf,
out_file: PathBuf,
}

fn main() {
let args = Args::parse();

match LvdFile::open(&args.in_file) {
Ok(lvd_file) => {
fs::write(&args.out_file, serde_yaml::to_string(&lvd_file).unwrap()).unwrap();
}
Err(binrw::Error::BadMagic { .. }) => {
// Magic doesn't match, is a yaml file
let contents = fs::read_to_string(&args.in_file).unwrap();
let lvd_file: LvdFile = serde_yaml::from_str(&contents).unwrap();

lvd_file.save(&args.out_file).unwrap();
}
Err(err) => {
eprintln!("Error: {:?}", err);
}
}
}
24 changes: 12 additions & 12 deletions src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl BinWrite for UnknownEntry {
&self.entry,
self.unk,
1u8,
string38(self.string.clone().to_string()),
string38(&self.string),
&self.unk2,
&self.unk3,
&self.unk3,
Expand All @@ -141,22 +141,22 @@ impl BinWrite for UnknownEntry {
}

#[derive(BinWrite)]
struct String38 {
struct String38<'a> {
#[binwrite(cstr, align_after(0x38))]
s: String
s: &'a str
}

fn string38(s: String) -> String38 {
fn string38(s: &str) -> String38 {
String38 { s }
}

#[derive(BinWrite)]
struct String40 {
struct String40<'a> {
#[binwrite(cstr, align_after(0x40))]
s: String
s: &'a str
}

fn string40(s: String) -> String40 {
fn string40(s: &str) -> String40 {
String40 { s }
}

Expand All @@ -168,9 +168,9 @@ impl BinWrite for LvdEntry {
fn write_options<W: Write>(&self, writer: &mut W, options: &WriterOption) -> io::Result<()> {
(
1u8,
string38(self.name.clone().into_string()),
string38(&self.name),
1u8,
string40(self.subname.clone().into_string()),
string40(&self.subname),
1u8,
&self.start_pos,
c_bool(&self.use_start),
Expand All @@ -180,7 +180,7 @@ impl BinWrite for LvdEntry {
&self.unk2,
self.unk3,
1u8,
string40(self.bone_name.clone().into_string()),
string40(&self.bone_name),
).write_options(writer, options)
}
}
Expand Down Expand Up @@ -283,9 +283,9 @@ impl BinWrite for PokemonTrainer {
1u8,
LvdList(&self.trainers),
1u8,
string40(self.platform_name.to_string()),
string40(&self.platform_name),
1u8,
string40(self.sub_name.to_string()),
string40(&self.sub_name),
).write_options(writer, options)
}
}
Expand Down

0 comments on commit 68d4f6e

Please sign in to comment.