use crate::Adt;
use crate::chunk::*;
use crate::error::Result;
use crate::version::AdtVersion;
use std::io::{Read, Seek, SeekFrom};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SplitAdtType {
Root,
Tex0,
Tex1,
Obj0,
Obj1,
Lod,
}
impl SplitAdtType {
pub fn from_filename(filename: &str) -> Self {
if filename.contains("_tex0") {
SplitAdtType::Tex0
} else if filename.contains("_tex1") {
SplitAdtType::Tex1
} else if filename.contains("_obj0") {
SplitAdtType::Obj0
} else if filename.contains("_obj1") {
SplitAdtType::Obj1
} else if filename.contains("_lod") {
SplitAdtType::Lod
} else {
SplitAdtType::Root
}
}
}
pub struct SplitAdtParser;
impl SplitAdtParser {
pub fn parse_tex0<R: Read + Seek>(reader: &mut R) -> Result<TexAdtData> {
let mut mtex = None;
let mut mcnk_tex_data = Vec::new();
let file_size = reader.seek(SeekFrom::End(0))?;
reader.seek(SeekFrom::Start(0))?;
let _mver = MverChunk::read(reader)?;
while let Ok(header) = ChunkHeader::read(reader) {
let current_pos = reader.stream_position()?;
if current_pos + header.size as u64 > file_size {
break;
}
match &header.magic {
b"MTEX" => {
mtex = Some(MtexChunk::read_with_header(
header,
&mut crate::ParserContext {
reader,
version: AdtVersion::Cataclysm,
position: current_pos as usize,
},
)?);
}
b"MCNK" => {
let mcnk_index = mcnk_tex_data.len();
mcnk_tex_data.push(McnkTexData {
index: mcnk_index,
mcly: None, mcal: None, });
reader.seek(SeekFrom::Current(header.size as i64))?;
}
_ => {
reader.seek(SeekFrom::Current(header.size as i64))?;
}
}
}
Ok(TexAdtData {
mtex,
mcnk_tex_data,
})
}
pub fn parse_obj0<R: Read + Seek>(reader: &mut R) -> Result<ObjAdtData> {
let mut mmdx = None;
let mut mmid = None;
let mut mwmo = None;
let mut mwid = None;
let mut mddf = None;
let mut modf = None;
let file_size = reader.seek(SeekFrom::End(0))?;
reader.seek(SeekFrom::Start(0))?;
let _mver = MverChunk::read(reader)?;
while let Ok(header) = ChunkHeader::read(reader) {
let current_pos = reader.stream_position()?;
if current_pos + header.size as u64 > file_size {
break;
}
match &header.magic {
b"MMDX" => {
mmdx = Some(MmdxChunk::read_with_header(
header,
&mut crate::ParserContext {
reader,
version: AdtVersion::Cataclysm,
position: current_pos as usize,
},
)?);
}
b"MMID" => {
mmid = Some(MmidChunk::read_with_header(
header,
&mut crate::ParserContext {
reader,
version: AdtVersion::Cataclysm,
position: current_pos as usize,
},
)?);
}
b"MWMO" => {
mwmo = Some(MwmoChunk::read_with_header(
header,
&mut crate::ParserContext {
reader,
version: AdtVersion::Cataclysm,
position: current_pos as usize,
},
)?);
}
b"MWID" => {
mwid = Some(MwidChunk::read_with_header(
header,
&mut crate::ParserContext {
reader,
version: AdtVersion::Cataclysm,
position: current_pos as usize,
},
)?);
}
b"MDDF" => {
mddf = Some(MddfChunk::read_with_header(
header,
&mut crate::ParserContext {
reader,
version: AdtVersion::Cataclysm,
position: current_pos as usize,
},
)?);
}
b"MODF" => {
modf = Some(ModfChunk::read_with_header(
header,
&mut crate::ParserContext {
reader,
version: AdtVersion::Cataclysm,
position: current_pos as usize,
},
)?);
}
_ => {
reader.seek(SeekFrom::Current(header.size as i64))?;
}
}
}
Ok(ObjAdtData {
mmdx,
mmid,
mwmo,
mwid,
mddf,
modf,
})
}
pub fn parse_obj1<R: Read + Seek>(reader: &mut R) -> Result<ObjAdtData> {
Self::parse_obj0(reader)
}
pub fn parse_tex1<R: Read + Seek>(reader: &mut R) -> Result<TexAdtData> {
Self::parse_tex0(reader)
}
pub fn parse_lod<R: Read + Seek>(reader: &mut R) -> Result<LodAdtData> {
let _file_size = reader.seek(SeekFrom::End(0))?;
reader.seek(SeekFrom::Start(0))?;
let mver = Some(MverChunk::read(reader)?);
Ok(LodAdtData {
mver,
simplified_data: Vec::new(), })
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct TexAdtData {
pub mtex: Option<MtexChunk>,
#[allow(dead_code)]
pub mcnk_tex_data: Vec<McnkTexData>,
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct McnkTexData {
#[allow(dead_code)]
pub index: usize,
#[allow(dead_code)]
pub mcly: Option<crate::mcnk_subchunks::MclySubchunk>,
#[allow(dead_code)]
pub mcal: Option<crate::mcnk_subchunks::McalSubchunk>,
}
#[derive(Debug)]
pub struct ObjAdtData {
pub mmdx: Option<MmdxChunk>,
pub mmid: Option<MmidChunk>,
pub mwmo: Option<MwmoChunk>,
pub mwid: Option<MwidChunk>,
pub mddf: Option<MddfChunk>,
pub modf: Option<ModfChunk>,
}
#[derive(Debug)]
pub struct LodAdtData {
pub mver: Option<MverChunk>,
pub simplified_data: Vec<u8>, }
pub fn merge_split_adt(
root: Adt,
tex0: Option<TexAdtData>,
_tex1: Option<TexAdtData>,
obj0: Option<ObjAdtData>,
_obj1: Option<ObjAdtData>,
_lod: Option<LodAdtData>,
) -> Adt {
let mut merged = root;
if let Some(tex_data) = tex0 {
if tex_data.mtex.is_some() {
merged.mtex = tex_data.mtex;
}
}
if let Some(obj_data) = obj0 {
merged.mmdx = obj_data.mmdx.or(merged.mmdx);
merged.mmid = obj_data.mmid.or(merged.mmid);
merged.mwmo = obj_data.mwmo.or(merged.mwmo);
merged.mwid = obj_data.mwid.or(merged.mwid);
merged.mddf = obj_data.mddf.or(merged.mddf);
merged.modf = obj_data.modf.or(merged.modf);
}
merged
}
pub struct SplitAdtLoader;
impl SplitAdtLoader {
pub fn load_tile<R, F>(_tile_x: u32, _tile_y: u32, mut _file_provider: F) -> Result<Adt>
where
R: Read + Seek,
F: FnMut(&str) -> Option<R>,
{
Err(crate::error::AdtError::UnsupportedVersion(0))
}
}