-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for bod1acc.bin + updateInfoParam files
- Loading branch information
Showing
17 changed files
with
533 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
use binrw::{binrw, BinReaderExt, BinWriterExt, NullString}; | ||
use binrw::io::{Cursor, Seek, SeekFrom}; | ||
use serde::{Serialize, Deserialize}; | ||
|
||
|
||
use super::{NuccBinaryParsed, NuccBinaryType}; | ||
|
||
const HEADER_SIZE: usize = 0x14; // Size of NUCC Binary headers | ||
|
||
|
||
// Format reversed by Zinogre344 | ||
#[allow(non_snake_case)] | ||
#[binrw] | ||
#[derive(Serialize, Deserialize, Debug)] | ||
pub struct Entry { | ||
#[serde(skip)] | ||
pub accessory_ptr: u64, | ||
|
||
#[serde(skip)] | ||
#[brw(pad_after = 8)] | ||
pub bone_name_ptr: u64, | ||
|
||
#[serde(skip)] | ||
#[brw(pad_after = 12)] | ||
pub accessory_location_ptr: u64, | ||
|
||
pub location: [f32; 3], | ||
|
||
#[brw(pad_after = 12)] | ||
pub rotation: [f32; 3], | ||
|
||
#[brw(pad_after = 4)] | ||
pub scale: [f32; 3], | ||
|
||
|
||
#[brw(ignore)] | ||
#[bw(map = |x| x.parse::<u8>().unwrap())] | ||
pub accessory: String, | ||
|
||
#[brw(ignore)] | ||
#[bw(map = |x| x.parse::<u8>().unwrap())] | ||
pub bone_name: String, | ||
|
||
#[brw(ignore)] | ||
#[bw(map = |x| x.parse::<u8>().unwrap())] | ||
pub accessory_location: String, | ||
} | ||
|
||
#[binrw] | ||
#[derive(Serialize, Deserialize, Debug)] | ||
pub struct BodAcc { | ||
#[serde(skip)] | ||
pub size: u32, | ||
|
||
#[serde(skip)] | ||
pub version: u32, | ||
|
||
pub entry_count: u32, | ||
|
||
#[serde(skip)] | ||
pub entry_ptr: u64, | ||
|
||
#[br(count = entry_count)] | ||
pub entries: Vec<Entry> | ||
} | ||
|
||
|
||
impl NuccBinaryParsed for BodAcc { | ||
fn binary_type(&self) -> NuccBinaryType { | ||
NuccBinaryType::BodAcc | ||
} | ||
|
||
fn extension(&self) -> String { | ||
String::from(".json") | ||
} | ||
|
||
fn serialize(&self) -> Vec<u8> { | ||
serde_json::to_string_pretty(self).unwrap().into() | ||
} | ||
|
||
fn deserialize(data: &[u8]) -> Self | ||
where | ||
Self: Sized, | ||
{ | ||
serde_json::from_slice(data).unwrap() | ||
} | ||
} | ||
|
||
impl From<&[u8]> for BodAcc { | ||
fn from(data: &[u8]) -> Self { | ||
let mut reader = Cursor::new(data); | ||
|
||
let size = reader.read_be::<u32>().unwrap(); | ||
let version = reader.read_le::<u32>().unwrap(); | ||
|
||
let entry_count = reader.read_le::<u32>().unwrap(); | ||
let entry_ptr = reader.read_le::<u64>().unwrap(); | ||
|
||
let mut entries = Vec::new(); | ||
entries.reserve_exact(entry_count as usize); // Make sure we have enough space to avoid reallocations | ||
|
||
for _ in 0..entry_count as usize { | ||
let entry = reader.read_le::<Entry>().unwrap(); | ||
entries.push(entry); | ||
} | ||
|
||
|
||
fn read_string_from_ptr(reader: &mut Cursor<&[u8]>, ptr: u64, curent_offset: u64) -> String { | ||
if ptr != 0 { | ||
reader.seek(SeekFrom::Start(curent_offset as u64)).unwrap(); | ||
reader.seek(SeekFrom::Current(ptr as i64)).unwrap(); | ||
reader.read_be::<NullString>().unwrap().to_string() | ||
} else { | ||
String::from("") | ||
} | ||
} | ||
|
||
for (current_offset, entry) in entries | ||
.iter_mut() | ||
.enumerate() | ||
.map(|(i, e)| (((0x60 * i + HEADER_SIZE) as u64, e))) | ||
{ | ||
entry.accessory = read_string_from_ptr(&mut reader, entry.accessory_ptr, current_offset); | ||
entry.bone_name = read_string_from_ptr(&mut reader, entry.bone_name_ptr, current_offset + 0x8); | ||
entry.accessory_location = read_string_from_ptr(&mut reader, entry.accessory_location_ptr, current_offset + 0x18); | ||
} | ||
|
||
BodAcc { | ||
size, | ||
version, | ||
entry_count, | ||
entry_ptr, | ||
entries | ||
} | ||
|
||
} | ||
|
||
} | ||
|
||
impl From<BodAcc> for Vec<u8> { | ||
fn from(mut bodacc: BodAcc) -> Self { | ||
let mut writer = Cursor::new(Vec::new()); | ||
|
||
bodacc.entry_count = bodacc.entries.len() as u32; // Update entry count | ||
|
||
writer.write_be(&bodacc.size).unwrap(); | ||
writer.write_le(&1000u32).unwrap(); // Write the version | ||
|
||
writer.write_le(&bodacc.entry_count).unwrap(); | ||
|
||
|
||
writer.write_le(&8u64).unwrap(); // Write the ptr to the entries | ||
|
||
|
||
writer.write_le(&bodacc.entries).unwrap(); | ||
|
||
fn write_ptr_to_string( | ||
writer: &mut Cursor<Vec<u8>>, | ||
string: &String, | ||
current_offset: u64, | ||
adjustment: u64, | ||
) { | ||
if !string.is_empty() { | ||
writer.seek(SeekFrom::End(0)).unwrap(); | ||
let string_pos = writer.seek(SeekFrom::End(0)).unwrap(); | ||
writer.write_be::<NullString>(&NullString::from(string.clone())).unwrap(); | ||
|
||
// Align to 8 bytes | ||
let pos = writer.seek(SeekFrom::Current(0)).unwrap() - string_pos; | ||
if 8 - (pos % 8) != 8 { | ||
writer.write_le::<Vec<u8>>(&vec![0; 8 - (pos % 8) as usize]).unwrap(); | ||
} | ||
|
||
writer.seek(SeekFrom::Start((current_offset + adjustment) as u64)).unwrap(); | ||
writer.write_le::<u64>(&(string_pos - current_offset - &adjustment)).unwrap(); | ||
|
||
} | ||
} | ||
for (current_offset, entry) in bodacc.entries | ||
.iter_mut() | ||
.enumerate() | ||
.map(|(i, e)| (((0x60 * i + HEADER_SIZE) as u64, e))) | ||
{ | ||
|
||
write_ptr_to_string(&mut writer, &entry.accessory, current_offset as u64, 0x0); | ||
write_ptr_to_string(&mut writer, &entry.bone_name, current_offset as u64, 0x8); | ||
write_ptr_to_string(&mut writer, &entry.accessory_location, current_offset as u64, 0x18); | ||
} | ||
|
||
// Go to the start of buffer and write the size | ||
writer.set_position(0); | ||
writer.write_be::<u32>(&((writer.get_ref().len() - 4) as u32)).unwrap(); | ||
|
||
writer.into_inner() | ||
|
||
} | ||
} |
Oops, something went wrong.