summaryrefslogtreecommitdiff
path: root/bck_funcs.py
diff options
context:
space:
mode:
authorOwl <isaclien9752@gmail.com>2025-09-26 14:32:34 -0400
committerOwl <isaclien9752@gmail.com>2025-09-26 14:32:34 -0400
commit70e647076418d114111aa76b5d3639a5b4271e94 (patch)
tree2e67e3c523818c7628497ff2f6e9e5c9645814d2 /bck_funcs.py
parent45dc6171705fd074657b0ed5bde2502431b74c4b (diff)
downloadblenxy-70e647076418d114111aa76b5d3639a5b4271e94.tar.gz
blenxy-70e647076418d114111aa76b5d3639a5b4271e94.zip
bcsv and other stuff
Diffstat (limited to 'bck_funcs.py')
-rw-r--r--bck_funcs.py167
1 files changed, 94 insertions, 73 deletions
diff --git a/bck_funcs.py b/bck_funcs.py
index e8482f8..73fd9de 100644
--- a/bck_funcs.py
+++ b/bck_funcs.py
@@ -1,5 +1,6 @@
-import os, struct, math
+import struct, math
from . import smg_common
+from . import file_ops
# python file to read the important information out of a BCK file
# will try its best to decode the information either on big/little endian
@@ -41,11 +42,11 @@ class smg_bck_raw:
def __str__(self):
rtn = " ### HEADER START\n"
- rtn += " Magic: %s\n" % (self.magic.__str__())
- rtn += " File type: %s\n" % (self.ftype.__str__())
- rtn += " File size: %s\n" % (self.file_size.__str__())
- rtn += " Section count: %s\n" % (self.section_count.__str__())
- rtn += " Unknown 1: %s\n" % (self.unknown1.__str__())
+ rtn += " Magic: %s\n" % (self.magic.__str__())
+ rtn += " File type: %s\n" % (self.ftype.__str__())
+ rtn += " File size: %s\n" % (self.file_size.__str__())
+ rtn += " Section count: %s\n" % (self.section_count.__str__())
+ rtn += " Unknown 1: %s\n" % (self.unknown1.__str__())
rtn += " ### HEADER END\n"
return rtn
@@ -72,26 +73,26 @@ class smg_bck_raw:
def __str__(self):
rtn = " ### ANK1 - START\n"
- rtn += " Magic: %s\n" % (self.magic.__str__())
- rtn += " Section size: %s\n" % (self.size.__str__())
- rtn += " Loop mode: %s\n" % (self.loop_mode.__str__())
- rtn += " Rotation left shift: %s\n" % (self.rot_lshift.__str__())
- rtn += " Anim length: %s\n" % (self.anim_length.__str__())
- rtn += " Bone count: %s\n" % (self.bone_count.__str__())
- rtn += " Scale array length: %s\n" % (self.scale_arr_length.__str__())
- rtn += " Rotation array length: %s\n" % (self.rot_arr_length.__str__())
- rtn += " Translation array length: %s\n" % (self.transl_arr_length.__str__())
- rtn += " Anim data offset: %s\n" % (self.anim_data_offset.__str__())
- rtn += " Scale array offset: %s\n" % (self.scale_arr_offset.__str__())
- rtn += " Rotation array offset: %s\n" % (self.rot_arr_offset.__str__())
- rtn += " Translation array offset: %s\n" % (self.transl_arr_offset.__str__())
- rtn += " Animation data:\n"
+ rtn += " Magic: %s\n" % (self.magic.__str__())
+ rtn += " Section size: %s\n" % (self.size.__str__())
+ rtn += " Loop mode: %s\n" % (self.loop_mode.__str__())
+ rtn += " Rotation left shift: %s\n" % (self.rot_lshift.__str__())
+ rtn += " Anim length: %s\n" % (self.anim_length.__str__())
+ rtn += " Bone count: %s\n" % (self.bone_count.__str__())
+ rtn += " Scale array length: %s\n" % (self.scale_arr_length.__str__())
+ rtn += " Rotation array length: %s\n" % (self.rot_arr_length.__str__())
+ rtn += " Translation array length: %s\n" % (self.transl_arr_length.__str__())
+ rtn += " Anim data offset: %s\n" % (self.anim_data_offset.__str__())
+ rtn += " Scale array offset: %s\n" % (self.scale_arr_offset.__str__())
+ rtn += " Rotation array offset: %s\n" % (self.rot_arr_offset.__str__())
+ rtn += " Translation array offset: %s\n" % (self.transl_arr_offset.__str__())
+ rtn += " Animation data: kf count, data index, interp mode\n"
for i in range(len(self.anim_data)):
rtn += " Bone %d\n" % (i)
rtn += "%s" % (self.anim_data[i].__str__())
- rtn += " Scale array: %s\n" % (self.scale_arr.__str__())
- rtn += " Rotation array: %s\n" % (self.rot_arr.__str__())
- rtn += " Translation array: %s\n" % (self.transl_arr.__str__())
+ rtn += " Scale array: %s\n" % (self.scale_arr.__str__())
+ rtn += " Rotation array: %s\n" % (self.rot_arr.__str__())
+ rtn += " Translation array: %s\n" % (self.transl_arr.__str__())
rtn += " ### ANK1 - END\n"
return rtn
@@ -109,15 +110,15 @@ class smg_bck_raw:
self.comp()] # transl z
def __str__(self):
- rtn = " Scale X: %s" % (self.comp[0].__str__())
- rtn += " Rot X: %s" % (self.comp[1].__str__())
- rtn += " Transl X: %s" % (self.comp[2].__str__())
- rtn += " Scale Y: %s" % (self.comp[3].__str__())
- rtn += " Rot Y: %s" % (self.comp[4].__str__())
- rtn += " Transl Y: %s" % (self.comp[5].__str__())
- rtn += " Scale Z: %s" % (self.comp[6].__str__())
- rtn += " Rot Z: %s" % (self.comp[7].__str__())
- rtn += " Transl Z: %s" % (self.comp[8].__str__())
+ rtn = " Scale X: %s" % (self.comp[0].__str__())
+ rtn += " Rot X: %s" % (self.comp[1].__str__())
+ rtn += " Transl X: %s" % (self.comp[2].__str__())
+ rtn += " Scale Y: %s" % (self.comp[3].__str__())
+ rtn += " Rot Y: %s" % (self.comp[4].__str__())
+ rtn += " Transl Y: %s" % (self.comp[5].__str__())
+ rtn += " Scale Z: %s" % (self.comp[6].__str__())
+ rtn += " Rot Z: %s" % (self.comp[7].__str__())
+ rtn += " Transl Z: %s" % (self.comp[8].__str__())
return rtn
@@ -143,12 +144,12 @@ class smg_bck_anim:
def __str__(self):
rtn = "### SMG_BCK_ANIM START\n"
- rtn += " Loop mode: %s\n" % (self.loop_mode.__str__())
- rtn += " Animation length: %s\n" % (self.anim_length.__str__())
- rtn += " Bone count: %s\n" % (self.bone_count.__str__())
- rtn += " Animation data:\n"
+ rtn += "Loop mode: %s\n" % (self.loop_mode.__str__())
+ rtn += "Animation length: %s\n" % (self.anim_length.__str__())
+ rtn += "Bone count: %s\n" % (self.bone_count.__str__())
+ rtn += "Animation data:\n"
for i in range(len(self.anim_data)):
- rtn += " Bone %d\n" % (i)
+ rtn += " Bone %d\n" % (i)
rtn += "%s" % (self.anim_data[i].__str__())
rtn += "### SMG_BCK_ANIM END"
return rtn
@@ -167,15 +168,15 @@ class smg_bck_anim:
self.comp()] # transl z
def __str__(self):
- rtn = " Scale X: %s" % (self.comp[0].__str__())
- rtn += " Rot X: %s" % (self.comp[1].__str__())
- rtn += " Transl X: %s" % (self.comp[2].__str__())
- rtn += " Scale Y: %s" % (self.comp[3].__str__())
- rtn += " Rot Y: %s" % (self.comp[4].__str__())
- rtn += " Transl Y: %s" % (self.comp[5].__str__())
- rtn += " Scale Z: %s" % (self.comp[6].__str__())
- rtn += " Rot Z: %s" % (self.comp[7].__str__())
- rtn += " Transl Z: %s" % (self.comp[8].__str__())
+ rtn = " Scale X: %s" % (self.comp[0].__str__())
+ rtn += " Rot X: %s" % (self.comp[1].__str__())
+ rtn += " Transl X: %s" % (self.comp[2].__str__())
+ rtn += " Scale Y: %s" % (self.comp[3].__str__())
+ rtn += " Rot Y: %s" % (self.comp[4].__str__())
+ rtn += " Transl Y: %s" % (self.comp[5].__str__())
+ rtn += " Scale Z: %s" % (self.comp[6].__str__())
+ rtn += " Rot Z: %s" % (self.comp[7].__str__())
+ rtn += " Transl Z: %s" % (self.comp[8].__str__())
return rtn
# anim_data
@@ -190,10 +191,10 @@ class smg_bck_anim:
def __str__(self):
rtn = "%s %s\n" % (self.kf_count, self.interp_mode)
- rtn += " time: %s\n" % (self.time.__str__())
- rtn += " value: %s\n" % (self.value.__str__())
- rtn += " in slope: %s\n" % (self.in_slope.__str__())
- rtn += " out slope: %s\n" % (self.out_slope.__str__())
+ rtn += " time: %s\n" % (self.time.__str__())
+ rtn += " value: %s\n" % (self.value.__str__())
+ rtn += " in slope: %s\n" % (self.in_slope.__str__())
+ rtn += " out slope: %s\n" % (self.out_slope.__str__())
return rtn
@@ -201,7 +202,6 @@ class smg_bck_anim:
bck_raw_info = None
bck_raw_error_str = "bck-raw-error: "
bck_anim_error_str = "bck-anim-error: "
-pad_str = "hoot"
f = None
# main function
@@ -286,7 +286,8 @@ def read_bck_file(filepath):
def pre_read_bck_file(filepath):
# check its size first
- if (os.path.getsize(filepath) <= 32):
+ file_size = file_ops.get_file_size(filepath)
+ if (file_size <= 32):
return bck_raw_error_str + "file size"
# make global variables editable
@@ -325,7 +326,7 @@ def pre_read_bck_file(filepath):
# file size
bck_raw_info.header.file_size = struct.unpack(endian_ch + "I", f.read(4))[0]
- if (bck_raw_info.header.file_size != os.path.getsize(filepath)):
+ if (bck_raw_info.header.file_size != file_ops.get_file_size(filepath)):
return bck_raw_error_str + "file size"
# section count
@@ -375,23 +376,23 @@ def pre_read_bck_file(filepath):
# bone animation data offset
bck_raw_info.ank1.anim_data_offset = struct.unpack(endian_ch + "I", f.read(4))[0]
- if (bck_raw_info.ank1.anim_data_offset
- + (bck_raw_info.ank1.bone_count * 9 * 6) > bck_raw_info.ank1.size):
+ if ((bck_raw_info.ank1.anim_data_offset + (bck_raw_info.ank1.bone_count * 9 * 6) > bck_raw_info.ank1.size)
+ or (bck_raw_info.ank1.anim_data_offset % 4 != 0)):
return bck_raw_error_str + "ank1 bone animation data offset"
# scale array offset
bck_raw_info.ank1.scale_arr_offset = struct.unpack(endian_ch + "I", f.read(4))[0]
- if (bck_raw_info.ank1.scale_arr_offset
- + (bck_raw_info.ank1.scale_arr_length * 4) > bck_raw_info.ank1.size):
+ if ((bck_raw_info.ank1.scale_arr_offset + (bck_raw_info.ank1.scale_arr_length * 4) > bck_raw_info.ank1.size)
+ or (bck_raw_info.ank1.scale_arr_offset % 4 != 0)):
return bck_raw_error_str + "ank1 scale array offset"
# rotation array offset
bck_raw_info.ank1.rot_arr_offset = struct.unpack(endian_ch + "I", f.read(4))[0]
- if (bck_raw_info.ank1.rot_arr_offset
- + (bck_raw_info.ank1.rot_arr_length * 2) > bck_raw_info.ank1.size):
+ if ((bck_raw_info.ank1.rot_arr_offset + (bck_raw_info.ank1.rot_arr_length * 2) > bck_raw_info.ank1.size)
+ or (bck_raw_info.ank1.rot_arr_offset % 4 != 0)):
return bck_raw_error_str + "ank1 rotation array offset"
# translation array offset
bck_raw_info.ank1.transl_arr_offset = struct.unpack(endian_ch + "I", f.read(4))[0]
- if (bck_raw_info.ank1.transl_arr_offset
- + (bck_raw_info.ank1.transl_arr_length * 4) > bck_raw_info.ank1.size):
+ if ((bck_raw_info.ank1.transl_arr_offset + (bck_raw_info.ank1.transl_arr_length * 4) > bck_raw_info.ank1.size)
+ or (bck_raw_info.ank1.transl_arr_offset % 4 != 0)):
return bck_raw_error_str + "ank1 translation array offset"
# refer to the offsets to read the animation data always (SMG does this)
@@ -550,7 +551,7 @@ def check_smg_bck_anim(anim):
# assumes angles are in radians
# and that the timings between the keyframes are t0 = 0 and tf = 1
# (cubic hermite spline)
-def create_smg_bck_raw(anim):
+def create_smg_bck_raw(anim, use_std_pad_size):
# calls check_smg_bck_anim()
result = check_smg_bck_anim(anim)
@@ -716,21 +717,26 @@ def create_smg_bck_raw(anim):
raw.ank1.transl_arr = arr
# assign these variables now
- # dont be crazy with it an assign the data tables to the "standard offsets"
raw.ank1.scale_arr_length = len(raw.ank1.scale_arr)
raw.ank1.rot_arr_length = len(raw.ank1.rot_arr)
raw.ank1.transl_arr_length = len(raw.ank1.transl_arr)
pad_str = smg_common.padding()
- raw.ank1.anim_data_offset = 0x40 # yes
+
+ # decide to use standard/compact padding sizes
+ pad_byte_align = 32
+ raw.ank1.anim_data_offset = 0x40
+ if (use_std_pad_size == False):
+ pad_byte_align = 4
+ raw.ank1.anim_data_offset = 0x24
raw.ank1.scale_arr_offset = raw.ank1.anim_data_offset + (raw.ank1.bone_count * 9 * 6)
- raw.ank1.scale_arr_offset += len(pad_str.string_fill(32, raw.ank1.scale_arr_offset))
+ raw.ank1.scale_arr_offset += len(pad_str.string_fill(pad_byte_align, raw.ank1.scale_arr_offset))
raw.ank1.rot_arr_offset = raw.ank1.scale_arr_offset + (raw.ank1.scale_arr_length * 4)
- raw.ank1.rot_arr_offset += len(pad_str.string_fill(32, raw.ank1.rot_arr_offset))
+ raw.ank1.rot_arr_offset += len(pad_str.string_fill(pad_byte_align, raw.ank1.rot_arr_offset))
raw.ank1.transl_arr_offset = raw.ank1.rot_arr_offset + (raw.ank1.rot_arr_length * 2)
- raw.ank1.transl_arr_offset += len(pad_str.string_fill(32, raw.ank1.transl_arr_offset))
+ raw.ank1.transl_arr_offset += len(pad_str.string_fill(pad_byte_align, raw.ank1.transl_arr_offset))
# section size and file size
raw.ank1.size = raw.ank1.transl_arr_offset + (raw.ank1.transl_arr_length * 4)
- raw.ank1.size += len(pad_str.string_fill(32, raw.ank1.size))
+ raw.ank1.size += len(pad_str.string_fill(pad_byte_align, raw.ank1.size))
raw.header.file_size = 32 + raw.ank1.size
# done!
@@ -766,18 +772,27 @@ def write_smg_bck_raw(raw, filepath, endian_ch):
f.write(struct.pack(endian_ch + "I", raw.ank1.rot_arr_offset))
f.write(struct.pack(endian_ch + "I", raw.ank1.transl_arr_offset))
pad = smg_common.padding()
- f.write(pad.string_fill(32, 0x24))
+ i = 0
+ while (f.tell() - 32 != raw.ank1.anim_data_offset):
+ f.write(pad.string[i].encode("ascii"))
+ i += 1
# anim data
for i in range(raw.ank1.bone_count):
for j in range(9):
f.write(struct.pack(endian_ch + "H", raw.ank1.anim_data[i].comp[j].keyframe_count))
f.write(struct.pack(endian_ch + "H", raw.ank1.anim_data[i].comp[j].anim_data_index))
f.write(struct.pack(endian_ch + "H", raw.ank1.anim_data[i].comp[j].interpolation_mode))
- f.write(pad.string_fill(32, raw.ank1.anim_data_offset + (raw.ank1.bone_count * 9 * 6)))
+ i = 0
+ while (f.tell() - 32 != raw.ank1.scale_arr_offset):
+ f.write(pad.string[i].encode("ascii"))
+ i += 1
# scale array
for i in range(raw.ank1.scale_arr_length):
f.write(struct.pack(endian_ch + "f", raw.ank1.scale_arr[i]))
- f.write(pad.string_fill(32, raw.ank1.scale_arr_offset + (raw.ank1.scale_arr_length * 4)))
+ i = 0
+ while (f.tell() - 32 != raw.ank1.rot_arr_offset):
+ f.write(pad.string[i].encode("ascii"))
+ i += 1
# rotation array
for i in range(raw.ank1.rot_arr_length):
# check if the slope is larger in magnitude than the max representation container
@@ -788,11 +803,17 @@ def write_smg_bck_raw(raw, filepath, endian_ch):
elif (value < -0x7FFF):
value = -0x7FFF
f.write(struct.pack(endian_ch + "h", value))
- f.write(pad.string_fill(32, raw.ank1.rot_arr_offset + (raw.ank1.rot_arr_length * 2)))
+ i = 0
+ while (f.tell() - 32 != raw.ank1.transl_arr_offset):
+ f.write(pad.string[i].encode("ascii"))
+ i += 1
# translation array
for i in range(raw.ank1.transl_arr_length):
f.write(struct.pack(endian_ch + "f", raw.ank1.transl_arr[i]))
- f.write(pad.string_fill(32, raw.ank1.transl_arr_offset + (raw.ank1.transl_arr_length * 4)))
+ i = 0
+ while (f.tell() != raw.header.file_size):
+ f.write(pad.string[i].encode("ascii"))
+ i += 1
# done!
f.close()