1#![allow(unused_variables)] use std::io::{Cursor, SeekFrom};
7
8use crate::crc::XivCrc32;
9use crate::{ByteSpan, common_file_operations::read_bool_from};
10use binrw::{BinRead, binread};
11
12#[binread]
13#[br(little, import {
14 strings_offset: u32
15})]
16#[derive(Debug)]
17#[allow(unused)]
18pub struct ResourceParameter {
19 id: u32,
20 #[br(temp)]
21 local_string_offset: u32,
22 #[br(temp)]
23 string_length: u16,
24
25 unknown: u16,
26
27 pub slot: u16,
28 size: u16,
29
30 #[br(seek_before = SeekFrom::Start(strings_offset as u64 + local_string_offset as u64))]
31 #[br(count = string_length, map = | x: Vec<u8> | String::from_utf8(x).unwrap().trim_matches(char::from(0)).to_string())]
32 #[br(restore_position)]
33 pub name: String,
34}
35
36#[binread]
37#[br(little, import {
38 version: u32,
39 shader_data_offset: u32,
40 strings_offset: u32,
41 is_vertex: bool
42})]
43#[derive(Debug)]
44#[allow(unused)]
45pub struct Shader {
46 data_offset: u32,
47 data_size: u32,
48
49 scalar_parameter_count: u16,
50 resource_parameter_count: u16,
51 uav_parameter_count: u16,
52 texture_count: u16,
53
54 #[br(count = if version >= 0x0D01 { 4 } else { 0 } )]
55 unk_data: Vec<u8>,
56
57 #[br(args { count: scalar_parameter_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
58 pub scalar_parameters: Vec<ResourceParameter>,
59 #[br(args { count: resource_parameter_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
60 pub resource_parameters: Vec<ResourceParameter>,
61 #[br(args { count: uav_parameter_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
62 pub uav_parameters: Vec<ResourceParameter>,
63 #[br(args { count: texture_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
64 pub texture_parameters: Vec<ResourceParameter>,
65
66 #[br(seek_before = SeekFrom::Start(shader_data_offset as u64 + data_offset as u64 + if is_vertex { 8 } else { 0 }))]
69 #[br(count = data_size)]
70 #[br(restore_position)]
71 pub bytecode: Vec<u8>,
72}
73
74#[binread]
75#[derive(Debug, Clone, Copy)]
76#[repr(C)]
77#[allow(unused)]
78pub struct MaterialParameter {
79 id: u32,
80 byte_offset: u16,
81 byte_size: u16,
82}
83
84#[binread]
85#[derive(Debug, Clone, Copy)]
86#[repr(C)]
87#[allow(unused)]
88pub struct Key {
89 pub id: u32,
90 pub default_value: u32,
91}
92
93#[binread]
94#[repr(C)]
95#[br(little, import {
96 version: u32,
97})]
98#[derive(Debug, Clone, Copy)]
99#[allow(unused)]
100pub struct Pass {
101 id: u32,
102 vertex_shader: u32,
103 #[brw(pad_after = if version >= 0x0D01 { 12 } else { 0 })]
104 pixel_shader: u32,
105}
106
107#[binread]
108#[derive(Debug)]
109#[allow(unused)]
110pub struct NodeAlias {
111 selector: u32,
112 node: u32,
113}
114
115#[binread]
116#[br(little, import {
117 version: u32,
118 system_key_count: u32,
119 scene_key_count: u32,
120 material_key_count: u32,
121 subview_key_count: u32
122})]
123#[derive(Debug)]
124#[allow(unused)]
125pub struct Node {
126 pub selector: u32,
127 pub pass_count: u32,
128 pub pass_indices: [u8; 16],
129
130 #[br(count = if version >= 0x0D01 { 8 } else { 0 } )]
131 unk_data: Vec<u8>,
132
133 #[br(count = system_key_count)]
134 pub system_keys: Vec<u32>,
135 #[br(count = scene_key_count)]
136 pub scene_keys: Vec<u32>,
137 #[br(count = material_key_count)]
138 pub material_keys: Vec<u32>,
139 #[br(count = subview_key_count)]
140 pub subview_keys: Vec<u32>,
141 #[br(args { count: pass_count as usize, inner: PassBinReadArgs { version }})]
142 pub passes: Vec<Pass>,
143}
144
145#[binread]
146#[br(little)]
147#[br(magic = b"ShPk")]
148#[derive(Debug)]
149#[allow(dead_code, unused)]
150pub struct ShaderPackage {
151 version: u32,
153
154 #[br(count = 4)]
156 #[bw(pad_size_to = 4)]
157 #[bw(map = |x : &String | x.as_bytes())]
158 #[br(map = | x: Vec<u8> | String::from_utf8(x).unwrap().trim_matches(char::from(0)).to_string())]
159 format: String,
160
161 file_length: u32,
162 shader_data_offset: u32,
163 strings_offset: u32,
164
165 vertex_shader_count: u32,
166 pixel_shader_count: u32,
167
168 pub material_parameters_size: u32,
169 material_parameter_count: u16,
170
171 #[br(map = read_bool_from::<u16>)]
172 has_mat_param_defaults: bool,
173 scalar_parameter_count: u32,
174 sampler_count: u16,
175 texture_count: u16,
176 uav_count: u32,
177
178 system_key_count: u32,
179 scene_key_count: u32,
180 material_key_count: u32,
181 node_count: u32,
182 node_alias_count: u32,
183
184 #[br(count = if version >= 0x0D01 { 12 } else { 0 } )]
185 unk_data: Vec<u8>,
186
187 #[br(args { count: vertex_shader_count as usize, inner : ShaderBinReadArgs { version, is_vertex: true, shader_data_offset, strings_offset }})]
189 pub vertex_shaders: Vec<Shader>,
190 #[br(args { count: pixel_shader_count as usize, inner: ShaderBinReadArgs { version, is_vertex: false, shader_data_offset, strings_offset } })]
191 pub pixel_shaders: Vec<Shader>,
192
193 #[br(count = material_parameter_count)]
194 pub material_parameters: Vec<MaterialParameter>,
195
196 #[br(count = if has_mat_param_defaults { (material_parameters_size as i32) >> 2i32 } else { 0 })]
197 mat_param_defaults: Vec<f32>,
198
199 #[br(args { count: scalar_parameter_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
200 scalar_parameters: Vec<ResourceParameter>,
201 #[br(args { count: sampler_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
202 sampler_parameters: Vec<ResourceParameter>,
203 #[br(args { count: texture_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
204 texture_parameters: Vec<ResourceParameter>,
205 #[br(args { count: uav_count as usize, inner: ResourceParameterBinReadArgs { strings_offset }})]
206 uav_parameters: Vec<ResourceParameter>,
207
208 #[br(count = system_key_count)]
209 pub system_keys: Vec<Key>,
210 #[br(count = scene_key_count)]
211 pub scene_keys: Vec<Key>,
212 #[br(count = material_key_count)]
213 pub material_keys: Vec<Key>,
214
215 pub sub_view_key1_default: u32,
216 pub sub_view_key2_default: u32,
217
218 #[br(args { count: node_count as usize, inner: NodeBinReadArgs { version, system_key_count, scene_key_count, material_key_count, subview_key_count: 2 }})]
219 pub nodes: Vec<Node>,
220
221 #[br(ignore)]
222 node_selectors: Vec<(u32, u32)>,
223
224 #[br(count = node_alias_count)]
225 node_aliases: Vec<NodeAlias>,
226}
227
228const SELECTOR_MULTIPLER: u32 = 31;
229
230impl ShaderPackage {
231 pub fn from_existing(buffer: ByteSpan) -> Option<ShaderPackage> {
233 let mut cursor = Cursor::new(buffer);
234 let mut package = ShaderPackage::read(&mut cursor).ok()?;
235
236 for (i, node) in package.nodes.iter().enumerate() {
237 package.node_selectors.push((node.selector, i as u32));
238 }
239 for alias in &package.node_aliases {
240 package.node_selectors.push((alias.selector, alias.node));
241 }
242
243 Some(package)
244 }
245
246 pub fn find_node(&self, selector: u32) -> Option<&Node> {
247 for (sel, node) in &self.node_selectors {
248 if *sel == selector {
249 return Some(&self.nodes[*node as usize]);
250 }
251 }
252
253 None
254 }
255
256 pub fn build_selector_from_all_keys(
257 system_keys: &[u32],
258 scene_keys: &[u32],
259 material_keys: &[u32],
260 subview_keys: &[u32],
261 ) -> u32 {
262 Self::build_selector_from_keys(
263 Self::build_selector(system_keys),
264 Self::build_selector(scene_keys),
265 Self::build_selector(material_keys),
266 Self::build_selector(subview_keys),
267 )
268 }
269
270 pub fn build_selector_from_keys(
271 system_key: u32,
272 scene_key: u32,
273 material_key: u32,
274 subview_key: u32,
275 ) -> u32 {
276 Self::build_selector(&[system_key, scene_key, material_key, subview_key])
277 }
278
279 pub fn build_selector(keys: &[u32]) -> u32 {
280 let mut selector: u32 = 0;
281 let mut multiplier: u32 = 1;
282
283 for key in keys {
284 selector = selector.wrapping_add(key.wrapping_mul(multiplier));
285 multiplier = multiplier.wrapping_mul(SELECTOR_MULTIPLER);
286 }
287
288 selector
289 }
290
291 pub fn crc(str: &str) -> u32 {
292 XivCrc32::from(str).crc
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use std::fs::read;
299 use std::path::PathBuf;
300
301 use super::*;
302
303 #[test]
304 fn test_invalid() {
305 let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
306 d.push("resources/tests");
307 d.push("random");
308
309 ShaderPackage::from_existing(&read(d).unwrap());
311 }
312
313 #[test]
314 fn test_crc() {
315 assert_eq!(ShaderPackage::crc("PASS_0"), 0xC5A5389C);
316 assert_eq!(ShaderPackage::crc("DecodeDepthBuffer"), 0x2C6C023C);
317 assert_eq!(ShaderPackage::crc("g_Sampler"), 0x88408C04);
318 }
319
320 #[test]
321 fn test_selector() {
322 let selector = ShaderPackage::build_selector_from_all_keys(
323 &[],
324 &[
325 ShaderPackage::crc("TransformViewSkin"),
326 ShaderPackage::crc("GetAmbientLight_SH"),
327 ShaderPackage::crc("GetReflectColor_Texture"),
328 ShaderPackage::crc("GetAmbientOcclusion_None"),
329 ShaderPackage::crc("ApplyDitherClipOff"),
330 ],
331 &[3756477356, 1556481461, 1111668802, 428675533],
332 &[
333 ShaderPackage::crc("Default"),
334 ShaderPackage::crc("SUB_VIEW_MAIN"),
335 ],
336 );
337
338 assert_eq!(selector, 0x1075AE91);
339 }
340}