#![allow(unused_variables)]
use std::io::Cursor;
use std::io::SeekFrom;
use crate::ByteSpan;
use crate::common_file_operations::read_string;
use crate::common_file_operations::read_string_until_null;
use crate::common_file_operations::write_string;
use binrw::BinRead;
use binrw::binrw;
#[binrw]
#[derive(Debug)]
#[brw(import(name: &str))]
#[brw(little)]
pub enum NodeData {
#[br(pre_assert(name == "CTRL"))]
CTRL(CTRLNode),
#[br(pre_assert(name == "CTIS"))]
CTIS(CTISNode),
#[br(pre_assert(name == "CTDS"))]
CTDS(CTDSNode),
#[br(pre_assert(name == "CTTL"))]
CTTL(CTTLNode),
Unknown,
}
#[binrw]
#[derive(Debug)]
#[brw(little)]
pub struct CutsceneNode {
#[br(count = 4)]
#[bw(pad_size_to = 4)]
#[bw(map = write_string)]
#[br(map = read_string)]
pub name: String,
size: u32,
data_offset: u32,
#[br(seek_before = SeekFrom::Current(data_offset as i64 - 4))]
#[br(restore_position)]
#[br(args(&name))]
pub node_data: NodeData,
data_size: u32,
}
#[binrw]
#[derive(Debug)]
#[brw(little)]
pub struct StringNode {
#[br(temp)]
#[bw(ignore)]
offset: u32,
#[br(seek_before = SeekFrom::Current(offset as i64 - 4))]
#[br(restore_position, parse_with = read_string_until_null)]
#[bw(ignore)]
pub value: String,
#[br(temp)]
#[bw(ignore)]
unk1: u32, }
#[binrw]
#[brw(magic = b"CUTB")]
#[derive(Debug)]
#[brw(little)]
pub struct Cutscene {
size_of_file: u32,
num_nodes: u32,
#[br(count = num_nodes)]
pub nodes: Vec<CutsceneNode>,
}
#[binrw]
#[derive(Debug)]
#[brw(little)]
pub struct CTRLNode {
size: u32, num_string_nodes: u32,
unk2: u32,
unk3: u32,
unk4: u32,
unk5: u32,
#[br(count = num_string_nodes)]
string_nodes: Vec<StringNode>,
}
#[binrw]
#[derive(Debug)]
#[brw(little)]
pub struct CTISNode {
size: u32, unk1: u32,
}
#[binrw]
#[derive(Debug)]
#[brw(little)]
pub struct CTDSNode {
size: u32, unk1: [u32; 15],
num_entries: u32,
unk2: u32,
offset_to_level: u32,
#[br(seek_before = SeekFrom::Current(offset_to_level as i64 - 76))] #[br(restore_position, parse_with = read_string_until_null)]
#[bw(ignore)]
level_name: String,
unk3: [u32; 2], #[br(count = num_entries)]
entries: Vec<u64>,
}
#[binrw]
#[derive(Debug)]
#[brw(little)]
pub struct CTTLNode {
#[br(count = 4)]
#[bw(pad_size_to = 4)]
#[bw(map = write_string)]
#[br(map = read_string)]
name: String,
size: u32,
node_count: u32,
#[br(count = node_count)]
node: Vec<TimelineNode>,
}
#[binrw]
#[derive(Debug)]
#[brw(little)]
pub struct TimelineNode {
#[br(count = 4)]
#[bw(pad_size_to = 4)]
#[bw(map = write_string)]
#[br(map = read_string)]
name: String,
size: u32,
#[br(count = size - 8)]
data: Vec<u8>,
}
impl Cutscene {
pub fn from_existing(buffer: ByteSpan) -> Option<Cutscene> {
let mut cursor = Cursor::new(buffer);
Cutscene::read(&mut cursor).ok()
}
}
#[cfg(test)]
mod tests {
use std::{fs::read, path::PathBuf};
use super::*;
#[test]
fn test_invalid() {
let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
d.push("resources/tests");
d.push("random");
Cutscene::from_existing(&read(d).unwrap());
}
}