Skip to content

Instantly share code, notes, and snippets.

@uyjulian
Last active October 1, 2025 02:21
Show Gist options
  • Save uyjulian/9d25961af34ef46d9960afc4c6ac4553 to your computer and use it in GitHub Desktop.
Save uyjulian/9d25961af34ef46d9960afc4c6ac4553 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# Attempting to figure out shader filenames for FDK (ED9 / Kuro no Kiseki) mdl format materials.
# Example: basic#3f0668ce.fxo
import os
import sys
import json
import zlib
def file_iter(path, ext2):
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
ext = os.path.splitext(filename)[1]
if ext != "" and ext.lower().endswith(ext2):
yield os.path.join(dirpath, filename)
def calc_hash(instr):
return zlib.crc32(instr, len(instr) ^ 0xFFFFFFFF) ^ 0xFFFFFFFF
shaders_all = []
with open("shader_list.txt", "r") as f:
for l in f.readlines():
strx = l.rstrip()
if strx != "":
shaders_all.append(strx)
matinfo_all = []
for filepath in file_iter("ed6_1r_matinfo", ".json"):
with open(filepath, "r") as f:
matinfo_all.append(json.load(f))
print(len(matinfo_all))
def gen_variant(base, mat):
arr = base[:]
if "" in arr:
arr.remove("")
matswitches = mat["material_switches"]
for matswitch in mat["material_switch_order"]:
matswitch_append = ""
matswitch_val = matswitches[matswitch]
if matswitch_val != 0xFFFFFFFF and matswitch_val >= 0x80000000:
raise Exception("Out of range value not yet implemented")
if matswitch_val != 0xFFFFFFFF:
matswitch_append = " %d" % matswitch_val
arr.append(matswitch + matswitch_append)
return arr
shader_dic = {}
shader_variant_dic = {}
for matinfo in matinfo_all:
for mat in matinfo:
shader_name = mat["shader_name"]
str3 = mat["str3"]
if shader_name != str3:
raise Exception("shader name not equal to str3")
unk_int3 = mat["unk_int3"]
# has_shadow = (unk_int3 & 1) != 0
has_shadow = True
variants_list = []
for i in range(2):
# is_tesselation = ""
# if (unk_int3 & 0x20) != 0:
# is_tesselation = "BUILD_TESSELLATION"
is_tesselation = ""
if i == 1:
is_tesselation = "BUILD_TESSELLATION"
variants_list.append(gen_variant(["COMPILE_VS", is_tesselation], mat))
variants_list.append(gen_variant(["COMPILE_VS", is_tesselation, "BUILD_SKIN"], mat))
if has_shadow:
variants_list.append(gen_variant(["COMPILE_VS", "BUILD_SHADOW", is_tesselation], mat))
variants_list.append(gen_variant(["COMPILE_VS", "BUILD_SHADOW", is_tesselation, "BUILD_SKIN"], mat))
variants_list.append(gen_variant(["COMPILE_VS", is_tesselation, "BUILD_TRANSPARENT"], mat))
variants_list.append(gen_variant(["COMPILE_VS", is_tesselation, "BUILD_SKIN", "BUILD_TRANSPARENT"], mat))
variants_list.append(gen_variant(["COMPILE_HS", is_tesselation], mat))
if has_shadow:
variants_list.append(gen_variant(["COMPILE_HS", "BUILD_SHADOW", is_tesselation], mat))
variants_list.append(gen_variant(["COMPILE_HS", is_tesselation, "BUILD_TRANSPARENT"], mat))
variants_list.append(gen_variant(["COMPILE_DS", is_tesselation], mat))
if has_shadow:
variants_list.append(gen_variant(["COMPILE_DS", "BUILD_SHADOW", is_tesselation], mat))
variants_list.append(gen_variant(["COMPILE_DS", is_tesselation, "BUILD_TRANSPARENT"], mat))
variants_list.append(gen_variant(["COMPILE_PS", is_tesselation], mat))
if has_shadow:
variants_list.append(gen_variant(["COMPILE_PS", "BUILD_SHADOW", is_tesselation], mat))
variants_list.append(gen_variant(["COMPILE_PS", is_tesselation], mat))
for variant in variants_list:
shader_file_name = "%s#%08x.fxo" % (str3, calc_hash("".join(variant).encode("ASCII")))
if shader_file_name not in shader_dic:
shader_dic[shader_file_name] = shader_file_name in shaders_all
if shader_dic[shader_file_name]:
shader_variant_dic[shader_file_name] = variant
true_has_count = 0
false_has_count = 0
for x in shader_dic:
if shader_dic[x]:
true_has_count += 1
else:
false_has_count += 1
print(true_has_count, false_has_count)
missingx = []
true_hit_count = 0
false_hit_count = 0
for x in shaders_all:
if x in shader_dic:
true_hit_count += 1
else:
missingx.append(x)
false_hit_count += 1
print(true_hit_count, false_hit_count)
with open("missingx.txt", "w") as f:
for x in missingx:
f.write(x + "\n")
jsondata = json.dumps(shader_variant_dic, indent=4).encode("utf-8")
with open("variants.json", "wb") as f:
f.write(jsondata)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment