glacier_texture/
rpkg.rs

1use std::io::Cursor;
2use binrw::{BinRead, BinWrite};
3use rpkg_rs::{GlacierResource, GlacierResourceError};
4use crate::mipblock::MipblockData;
5use crate::pack::TexturePackerError;
6use crate::texture_map::TextureMap;
7use crate::WoaVersion;
8
9
10impl From<rpkg_rs::WoaVersion> for WoaVersion {
11    fn from(value: rpkg_rs::WoaVersion) -> Self {
12        match value {
13            rpkg_rs::WoaVersion::HM2016 => { WoaVersion::HM2016 }
14            rpkg_rs::WoaVersion::HM2 => { WoaVersion::HM2 }
15            rpkg_rs::WoaVersion::HM3 => { WoaVersion::HM3 }
16        }
17    }
18}
19
20impl From<WoaVersion> for rpkg_rs::WoaVersion{
21    fn from(value: WoaVersion) -> Self {
22        match value {
23            WoaVersion::HM2016 => { rpkg_rs::WoaVersion::HM2016 }
24            WoaVersion::HM2 => { rpkg_rs::WoaVersion::HM2 }
25            WoaVersion::HM3 => { rpkg_rs::WoaVersion::HM3 }
26        }
27    }
28}
29
30impl GlacierResource for TextureMap {
31    type Output = TextureMap;
32
33    fn process_data<R: AsRef<[u8]>>(woa_version: rpkg_rs::WoaVersion, data: R) -> Result<Self::Output, GlacierResourceError> {
34        let mut stream = Cursor::new(data);
35        TextureMap::read_le_args(&mut stream, (WoaVersion::from(woa_version), )).map_err(|e| GlacierResourceError::ReadError(e.to_string()))
36    }
37
38    fn serialize(&self, _: rpkg_rs::WoaVersion) -> Result<Vec<u8>, GlacierResourceError> {
39        //TODO: woa version gets ignored currently. Getting the packer to accept TextureMap would allow for easy porting.
40        let mut writer = Cursor::new(Vec::new());
41        self.write_le_args(&mut writer, ())
42            .map_err(TexturePackerError::SerializationError).map_err(|e| GlacierResourceError::ReadError(e.to_string()))?; //TODO: change this
43        Ok(writer.into_inner())
44    }
45
46    fn resource_type() -> [u8; 4] {
47        *b"TEXT"
48    }
49
50    fn video_memory_requirement(&self) -> u64 {
51        self.video_memory_requirement() as u64
52    }
53
54    fn system_memory_requirement(&self) -> u64 {
55        0xFFFFFFFF
56    }
57
58    fn should_scramble(&self) -> bool {
59        true
60    }
61
62    fn should_compress(&self) -> bool {
63        match self.version(){
64            WoaVersion::HM2016 => {true}
65            WoaVersion::HM2 |
66            WoaVersion::HM3 => {false}
67        }
68    }
69}
70
71impl GlacierResource for MipblockData{
72    type Output = MipblockData;
73
74    fn process_data<R: AsRef<[u8]>>(woa_version: rpkg_rs::WoaVersion, data: R) -> Result<Self::Output, GlacierResourceError> {
75        let mipblock = MipblockData::from_memory(data.as_ref(), woa_version.into()).map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
76        Ok(mipblock)
77    }
78
79    fn serialize(&self, woa_version: rpkg_rs::WoaVersion) -> Result<Vec<u8>, GlacierResourceError> {
80        if self.header.is_empty() && (woa_version == rpkg_rs::WoaVersion::HM2016 || woa_version == rpkg_rs::WoaVersion::HM2) {
81            return Err(GlacierResourceError::ReadError(format!("Cannot serialize to {woa_version:?} without header data :(")));
82        }
83        self.pack_to_vec(woa_version.into()).map_err( |e| GlacierResourceError::WriteError(format!("Texd packing error: {e}")))
84    }
85
86    fn resource_type() -> [u8; 4] {
87        *b"TEXD"
88    }
89
90    fn video_memory_requirement(&self) -> u64 {
91        self.video_memory_requirement() as u64
92    }
93
94    fn system_memory_requirement(&self) -> u64 {
95        0xFFFFFFFF
96    }
97
98    fn should_scramble(&self) -> bool {
99        false
100    }
101
102    fn should_compress(&self) -> bool {
103        false
104    }
105}
106
107pub fn full_texture(manager: &rpkg_rs::resource::partition_manager::PartitionManager, woa_version: rpkg_rs::WoaVersion, rrid: rpkg_rs::resource::runtime_resource_id::RuntimeResourceID) -> Result<TextureMap, GlacierResourceError> {
108    let res_info = manager.resource_info_from(&"chunk0".parse().unwrap(), &rrid).map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
109    let data = manager.read_resource_from("chunk0".parse().unwrap(), rrid).map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
110
111    let mut stream = Cursor::new(data);
112    let mut texture_map = TextureMap::read_le_args(&mut stream, (WoaVersion::from(woa_version), )).map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
113
114    if let Some((rrid, _)) = res_info.references().first(){
115        let texd_data = manager.read_resource_from("chunk0".parse().unwrap(), *rrid).map_err(|e| GlacierResourceError::ReadError(format!("Tried to load broken depend: {e}")))?;
116        let mipblock = MipblockData::from_memory(texd_data.as_slice(), woa_version.into()).map_err(|e| GlacierResourceError::ReadError(format!("Failed to read texd: {e}")))?;
117        texture_map.set_mipblock1(mipblock);
118    }
119    Ok(texture_map)
120}