1use crate::box_reflection::BoxReflectionCache;
2use crate::mipblock::MipblockData;
3use crate::pack::TexturePackerError;
4use crate::texture_map::TextureMap;
5use crate::GlacierGame;
6use binrw::{BinRead, BinWrite};
7use rpkg_rs::{GlacierResource, GlacierResourceError};
8use std::io::Cursor;
9
10impl From<rpkg_rs::WoaVersion> for GlacierGame {
11 fn from(value: rpkg_rs::WoaVersion) -> Self {
12 match value {
13 rpkg_rs::WoaVersion::HM2016 => GlacierGame::HM2016,
14 rpkg_rs::WoaVersion::HM2 => GlacierGame::HM2,
15 rpkg_rs::WoaVersion::HM3 => GlacierGame::HM3,
16 }
17 }
18}
19
20impl From<GlacierGame> for rpkg_rs::WoaVersion {
21 fn from(value: GlacierGame) -> Self {
22 match value {
23 GlacierGame::HM2016 => rpkg_rs::WoaVersion::HM2016,
24 GlacierGame::HM2 => rpkg_rs::WoaVersion::HM2,
25 GlacierGame::HM3 => rpkg_rs::WoaVersion::HM3,
26 GlacierGame::KNT => {
27 todo!()
28 }
29 }
30 }
31}
32
33impl GlacierResource for TextureMap {
34 type Output = TextureMap;
35
36 fn process_data<R: AsRef<[u8]>>(
37 glacier_game: rpkg_rs::WoaVersion,
38 data: R,
39 ) -> Result<Self::Output, GlacierResourceError> {
40 let mut stream = Cursor::new(data);
41 TextureMap::read_le_args(&mut stream, (GlacierGame::from(glacier_game),))
42 .map_err(|e| GlacierResourceError::ReadError(e.to_string()))
43 }
44
45 fn serialize(&self, _: rpkg_rs::WoaVersion) -> Result<Vec<u8>, GlacierResourceError> {
46 let mut writer = Cursor::new(Vec::new());
48 self.write_le_args(&mut writer, ())
49 .map_err(TexturePackerError::SerializationError)
50 .map_err(|e| GlacierResourceError::ReadError(e.to_string()))?; Ok(writer.into_inner())
52 }
53
54 fn resource_type() -> [u8; 4] {
55 *b"TEXT"
56 }
57
58 fn video_memory_requirement(&self) -> u64 {
59 self.video_memory_requirement() as u64
60 }
61
62 fn system_memory_requirement(&self) -> u64 {
63 0xFFFFFFFF
64 }
65
66 fn should_scramble(&self) -> bool {
67 true
68 }
69
70 fn should_compress(&self) -> bool {
71 match self.version() {
72 GlacierGame::HM2016 => true,
73 GlacierGame::HM2 | GlacierGame::HM3 | GlacierGame::KNT => false,
74 }
75 }
76}
77
78impl GlacierResource for MipblockData {
79 type Output = MipblockData;
80
81 fn process_data<R: AsRef<[u8]>>(
82 woa_version: rpkg_rs::WoaVersion,
83 data: R,
84 ) -> Result<Self::Output, GlacierResourceError> {
85 let mipblock = MipblockData::from_memory(data.as_ref(), woa_version.into())
86 .map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
87 Ok(mipblock)
88 }
89
90 fn serialize(&self, woa_version: rpkg_rs::WoaVersion) -> Result<Vec<u8>, GlacierResourceError> {
91 if self.header.is_empty()
92 && (woa_version == rpkg_rs::WoaVersion::HM2016
93 || woa_version == rpkg_rs::WoaVersion::HM2)
94 {
95 return Err(GlacierResourceError::ReadError(format!(
96 "Cannot serialize to {woa_version:?} without header data :("
97 )));
98 }
99 self.pack_to_vec(woa_version.into())
100 .map_err(|e| GlacierResourceError::WriteError(format!("Texd packing error: {e}")))
101 }
102
103 fn resource_type() -> [u8; 4] {
104 *b"TEXD"
105 }
106
107 fn video_memory_requirement(&self) -> u64 {
108 self.video_memory_requirement() as u64
109 }
110
111 fn system_memory_requirement(&self) -> u64 {
112 0xFFFFFFFF
113 }
114
115 fn should_scramble(&self) -> bool {
116 false
117 }
118
119 fn should_compress(&self) -> bool {
120 false
121 }
122}
123
124pub fn full_texture(
125 manager: &rpkg_rs::resource::partition_manager::PartitionManager,
126 woa_version: rpkg_rs::WoaVersion,
127 rrid: rpkg_rs::resource::runtime_resource_id::RuntimeResourceID,
128) -> Result<TextureMap, GlacierResourceError> {
129 let res_info = manager
130 .resource_info_from(&"chunk0".parse().unwrap(), &rrid)
131 .map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
132 let data = manager
133 .read_resource_from("chunk0".parse().unwrap(), rrid)
134 .map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
135
136 let mut stream = Cursor::new(data);
137 let mut texture_map = TextureMap::read_le_args(&mut stream, (GlacierGame::from(woa_version),))
138 .map_err(|e| GlacierResourceError::ReadError(e.to_string()))?;
139
140 if let Some((rrid, _)) = res_info.references().first() {
141 let texd_data = manager
142 .read_resource_from("chunk0".parse().unwrap(), *rrid)
143 .map_err(|e| {
144 GlacierResourceError::ReadError(format!("Tried to load broken depend: {e}"))
145 })?;
146 let mipblock = MipblockData::from_memory(texd_data.as_slice(), woa_version.into())
147 .map_err(|e| GlacierResourceError::ReadError(format!("Failed to read texd: {e}")))?;
148 texture_map.set_mipblock1(mipblock);
149 }
150 Ok(texture_map)
151}
152
153impl GlacierResource for BoxReflectionCache {
154 type Output = BoxReflectionCache;
155
156 fn process_data<R: AsRef<[u8]>>(
157 _: rpkg_rs::WoaVersion,
158 data: R,
159 ) -> Result<Self::Output, GlacierResourceError> {
160 BoxReflectionCache::from_memory(data.as_ref())
161 .map_err(|e| GlacierResourceError::ReadError(e.to_string()))
162 }
163
164 fn serialize(&self, _: rpkg_rs::WoaVersion) -> Result<Vec<u8>, GlacierResourceError> {
165 self.pack_to_vec()
166 .map_err(|e| GlacierResourceError::WriteError(format!("Boxc packing error: {e}")))
167 }
168
169 fn resource_type() -> [u8; 4] {
170 *b"BOXC"
171 }
172
173 fn video_memory_requirement(&self) -> u64 {
174 self.iter().map(|e| e.buffer_size() as u64).sum()
175 }
176
177 fn system_memory_requirement(&self) -> u64 {
178 0xffffffff
179 }
180
181 fn should_scramble(&self) -> bool {
182 true
183 }
184
185 fn should_compress(&self) -> bool {
186 true
187 }
188}