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