diff --git a/src/lcb.rs b/src/lcb.rs new file mode 100644 index 0000000..2e5964c --- /dev/null +++ b/src/lcb.rs @@ -0,0 +1,88 @@ +// SPDX-FileCopyrightText: 2025 Joshua Goins +// SPDX-License-Identifier: GPL-3.0-or-later + +use std::io::Cursor; + +use crate::ByteBuffer; +use crate::ByteSpan; +use binrw::BinRead; +use binrw::BinWrite; +use binrw::binrw; + +#[binrw] +#[derive(Debug)] +#[brw(little)] +#[brw(magic = b"LCB1")] +pub struct Lcb { + /// Including this header + pub file_size: u32, + /// Number of Lcc's + #[br(temp)] + #[bw(calc = lccs.len() as u32)] + lcc_count: u32, + #[br(count = lcc_count)] + pub lccs: Vec, +} + +#[binrw] +#[derive(Debug)] +#[brw(little)] +#[brw(magic = b"LCC1")] +pub struct Lcc { + #[br(temp)] + #[bw(calc = entries.len() as u32 + 1)] + pub num_entries: u32, + #[brw(pad_before = 4)] // empty? + pub unk1: u32, + pub unk2: u32, + // TODO: figure out what this is + // TODO: why is it -1? + #[br(count = num_entries - 1)] + pub entries: Vec, +} + +#[binrw] +#[derive(Debug)] +#[brw(little)] +pub struct LccEntry { + // TODO: figure out what this is + #[br(count = 32)] + pub unk1: Vec, +} + +impl Lcb { + /// Reads an existing UWB file + pub fn from_existing(buffer: ByteSpan) -> Option { + let mut cursor = Cursor::new(buffer); + Lcb::read(&mut cursor).ok() + } + + pub fn write_to_buffer(&self) -> Option { + let mut buffer = ByteBuffer::new(); + + { + let mut cursor = Cursor::new(&mut buffer); + self.write_le(&mut cursor).ok()?; + } + + Some(buffer) + } +} + +#[cfg(test)] +mod tests { + use std::fs::read; + use std::path::PathBuf; + + use super::*; + + #[test] + fn test_invalid() { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("resources/tests"); + d.push("random"); + + // Feeding it invalid data should not panic + Lcb::from_existing(&read(d).unwrap()); + } +} diff --git a/src/lib.rs b/src/lib.rs index 8e7b2ac..348297a 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,6 +140,9 @@ pub mod patchlist; /// Reading UWB files pub mod uwb; +/// Reading LCB files +pub mod lcb; + mod bcn; mod error;