diff --git a/Scripts/BRS-Dig-For-Bones.bms b/Scripts/BRS-Dig-For-Bones.bms new file mode 100644 index 0000000..d3a3d61 --- /dev/null +++ b/Scripts/BRS-Dig-For-Bones.bms @@ -0,0 +1,425 @@ +#Copyright 2024 - Brad D +#See LICENSE for copyright information. +#Please include this header and that license for any derivative works. + +startfunction print_header + print "# %NAME% Model Data" + print "\n" + print "---" + print "\n" + print "*Copyright 2024 - Brad D*" + print "\n" + print "*See LICENSE for copyright information.*" + print "\n" + print "*Please include this header and that license for any derivative works.*" + print "\n" + print "*NOTE: Only the documentation, tools and anything that's not directly a part of the game's data fall under this copyright. I don't claim any ownership of the game or any of its assets*" + print "\n" + print "---" +endfunction + +get NAME FILENAME +string NAME % "." +string NAME u NAME +get SIZE asize +set CHUNK 0x04 +set LINES SIZE +math LINES / CHUNK + +set MESHES_ARRAY 0 +set BONES_ARRAY 1 +set BONE_GROUPS_ARRAY 2 +set PADDING_OFFSETS_ARRAY 3 + +# Prepare for Bone Groups +set BONE_GROUP 0 + +# Get the Namespace +set NAMESPACE NAME +string NAMESPACE - "FCHR_" +strlen LENGTH NAMESPACE +do + string NAMESPACE - 1 + strlen LENGTH NAMESPACE +while LENGTH != 1 + +# Get the Boss Name +set BOSS_NAME NAME +set WRS_PART 0 +string BOSS_NAME - "FCHR_B_" +set WRS BOSS_NAME +strlen LENGTH BOSS_NAME +do + string BOSS_NAME - 1 + strlen LENGTH BOSS_NAME +while LENGTH != 3 + +if BOSS_NAME == "CYZ" + set BOSS_NAME "Shizu" +elseif BOSS_NAME == "KAL" + set BOSS_NAME "Karli" +elseif BOSS_NAME == "MAZ" + set BOSS_NAME "Mazuma" +elseif BOSS_NAME == "MEE" + set BOSS_NAME "Mii" +elseif BOSS_NAME == "NAF" + set BOSS_NAME "Nafe" +elseif BOSS_NAME == "RIR" + set BOSS_NAME "Lilio" +elseif BOSS_NAME == "ZAH" + set BOSS_NAME "Zaha" +else + string WRS - BOSS_NAME + set BOSS_NAME " White Rock Shooter" + strlen LENGTH WRS + + if WRS == "02" | WRS == "02P" + set WRS_PART 1 + endif +endif + +if WRS_PART == 0 + # Get the Part + set PART NAME + string PART r PART + strlen LENGTH PART + do + string PART - 1 + strlen LENGTH PART + while LENGTH != 1 +endif + +# Get the Mob Name; some monsters don't include normal vertex data, so they'll need heavy testing and / or workarounds if they have anything usable +set MOB_NAME NAME +set MOB_NO_VERTEX 0 +string MOB_NAME - "FCHR_M_" +strlen LENGTH MOB_NAME +do + string MOB_NAME - 1 + strlen LENGTH MOB_NAME +while LENGTH != 3 + +if MOB_NAME == "BAT" | MOB_NAME == "CUB" + set MOB_NO_VERTEX 1 +endif + +if NAMESPACE == "B" | NAMESPACE == "P" + if NAMESPACE == "B" + set NAMESPACE "Boss" + else + set NAMESPACE "Player" + endif + if WRS_PART == 0 + if PART == "B" + set PART "Accessories" + elseif PART == "P" | PART == 1 | PART == 2 + set PART "Arms / Weapons" + elseif PART == "0" + set PART == "Body" + elseif PART == "F" + set PART == "Unique" + endif + else + set PART "Accessories" + endif + set HAS_PART 1 +elseif NAMESPACE == "G" + set MOB_NO_VERTEX 1 + set NAMESPACE "Game Object / Gimmick" +elseif NAMESPACE == "T" + set MOB_NO_VERTEX 1 + set NAMESPACE "Test" +elseif NAMESPACE == "M" + set NAMESPACE "Mob" +elseif NAMESPACE == "S" + set NAMESPACE "Soldier" +elseif NAMESPACE == "W" + set MOB_NO_VERTEX 1 + set NAMESPACE "Weapon / Skill" +endif + +# Get the Bone Group based on amount of padding between this bone and the next +startfunction get_bone_group + set PADDING_OFFSET PREV_BONE + math PADDING_OFFSET + 0x18 + goto PADDING_OFFSET + get PADDING_OFFSET long + math PADDING_OFFSET + PREV_BONE + goto PADDING_OFFSET + set OFFSET PADDING_OFFSET + set PADDING_OFFSET BONE + math PADDING_OFFSET - OFFSET + string PADDING_OFFSET p "%x" PADDING_OFFSET + putarray PADDING_OFFSETS_ARRAY -1 PADDING_OFFSET + + # Get Bone Groups Array Size + getarray GROUP_SIZE BONE_GROUPS_ARRAY -0x80000000 + if GROUP_SIZE != 0 + set COUNT 0 + for j = 0 < GROUP_SIZE + getarray GROUP BONE_GROUPS_ARRAY j + if PADDING_OFFSET != GROUP + math COUNT + 1 + else + break + endif + if COUNT == GROUP_SIZE + putarray BONE_GROUPS_ARRAY -1 PADDING_OFFSET + endif + next j + else + putarray BONE_GROUPS_ARRAY 0 PADDING_OFFSET + endif +endfunction + +callfunction print_header 1 NAME + +# Find the meshes +goto 0 +set MESHES 0 +set BONES 0 +savepos CUR_POS +for i = 0 < LINES + goto CUR_POS + getdstring MAGIC_NUMBER 0x04 + if MAGIC_NUMBER == "PTMD" + math MESHES + 1 + putarray MESHES_ARRAY -1 CUR_POS + elseif MAGIC_NUMBER == "INSA" + math BONES + 1 + putarray BONES_ARRAY -1 CUR_POS + endif + set TMP CUR_POS + math TMP + CHUNK + set CUR_POS TMP +next i + +print "\n" +print "* Namespace: %NAMESPACE%" +if NAMESPACE == "Boss" + print "\n" + print "* Name: %BOSS_NAME%" +endif + +if HAS_PART == 1 + print "\n" + print "* Part: %PART%" +endif +print "\n" +print "---" +# Print UV Maps, Normal Maps, Texture Data +print "\n" +print "* UV Maps: Unknown" +print "\n" +print "* Normal Maps: Unknown" +print "\n" +print "* Textures: Unknown" +print "\n" +print "---" +print "\n" + +set MESHES_STRING "* Meshes: " +string MESHES_STRING + MESHES +print "%MESHES_STRING%" + +if MESHES != 0 + print "\n" + print "* Located At:" + for i = 0 < MESHES + getarray MESH MESHES_ARRAY i + string M p "%x" MESH + print "\n" + print " * %i%: 0x%M%" + next i +endif +print "\n" +print "---" +print "\n" + +# Vertex Data Functions based on Pattern +startfunction apply_boss_augmentations + # set up the offsets per boss here + set SHIZU_OFFSET 0x84 + set KARLI_OFFSET 0x00 + set MAZUMA_OFFSET -0x210 + set MII_OFFSET -0x84 + set NAFE_OFFSET 0x18c + set LILIO_OFFSET 0x3c + set WRS_OFFSET 0x210 + set ZAHA_OFFSET 0x50 + set OFFSET 0 + + if BOSS_NAME == "Shizu" + set OFFSET SHIZU_OFFSET + elseif BOSS_NAME == "Karli" + set OFFSET KARLI_OFFSET + elseif BOSS_NAME == "Mazuma" + set OFFSET MAZUMA_OFFSET + elseif BOSS_NAME == "Mii" + set OFFSET MII_OFFSET + elseif BOSS_NAME == "Nafe" + set OFFSET NAFE_OFFSET + elseif BOSS_NAME == "Lilio" + set OFFSET LILIO_OFFSET + elseif BOSS_NAME == "White Rock Shooter" + set OFFSET WRS_OFFSET + elseif BOSS_NAME == "Zaha" + set OFFSET ZAHA_OFFSET + endif + + math VD_OFFSET + OFFSET + goto VD_OFFSET + savepos CUR_POS +endfunction + +startfunction determine_packing_pattern +endfunction + +# Find the Vertex Data Section and print it to file +startfunction print_vertex_data_location + set VD_OFFSET BONE + math VD_OFFSET + 0x0c + goto VD_OFFSET + get VD_OFFSET long + if VD_OFFSET != 0 + set MOB_NO_VERTEX 1 + else + get VD_MAGIC_NUMBER long # Grab and store the real vertex data value from here + set VD_OFFSET BONE # Reset this value back to the top; we need to apply a special offset to that value to get to the proper location + math VD_OFFSET + 0x132c + endif + if MOB_NO_VERTEX == 0 + if NAMESPACE == "Boss" + print "BOSS FOUND" + callfunction apply_boss_augmentations 1 VD_OFFSET BOSS_NAME + endif + goto CUR_POS + get TMP long + if TMP == VD_MAGIC_NUMBER + goto CUR_POS + set VD_OFFSET CUR_POS + math VD_OFFSET + 0x0c # to get to the start of the vertex data; need to apply other factors + string VD_OFFSET p "%x" VD_OFFSET + print "\n" + print " * Vertex Data Address: 0x%VD_OFFSET%" + endif + endif +endfunction + +# Find the Animation Section +startfunction print_animation_location + set ANIM_OFFSET BONE + math ANIM_OFFSET + 0x14 + goto ANIM_OFFSET + get ANIM_OFFSET long + set CALCULATIONS 0 + if ANIM_OFFSET == 0x28 + math ANIM_OFFSET + BONE + # Find where the chain ends by adding 0x24 + set TYPE string "28" + set CALCULATIONS ANIM_OFFSET + math CALCULATIONS + 0x03 # Get the final byte because it's what tells how long the chain is + goto CALCULATIONS + get CALCULATIONS byte + # Fix some quirks where these two extremes don't function in expected ways + if CALCULATIONS == 0xff | CALCULATIONS == 0x00 + set CALCULATIONS 1 + endif + + set TOTAL 0 + for j = 0 < CALCULATIONS + set TOTAL_OFFSET ANIM_OFFSET + math TOTAL_OFFSET + 0x04 + goto TOTAL_OFFSET + get TOTAL_OFFSET long + math TOTAL + TOTAL_OFFSET + math ANIM_OFFSET + 0x24 + goto ANIM_OFFSET + next j + elseif ANIM_OFFSET == 0x20 + math ANIM_OFFSET + BONE + # Find where the chain ends by adding 0x08 and then checking for a specific value for the first byte + set TYPE string "20" + set TOTAL 0 + get CONTINUE byte + do + set PREV_AO ANIM_OFFSET + set TOTAL_OFFSET ANIM_OFFSET + math TOTAL_OFFSET + 0x04 + goto TOTAL_OFFSET + get TOTAL_OFFSET long + math TOTAL + TOTAL_OFFSET + math ANIM_OFFSET + 0x08 + goto ANIM_OFFSET + math CALCULATIONS + 1 + get CONTINUE byte + while CONTINUE == 1 + endif + string A p "%x" ANIM_OFFSET + string T p "%x" TOTAL + string C p "%x" CALCULATIONS + if CALCULATIONS < 0x10 + set X "0" + string X + C + set C X + endif + print "\n" + print " * Calculation Type: 0x%TYPE%" + print "\n" + print " * Calculations: 0x%C%" + print "\n" + print " * Calculation Result: 0x%T%" + print "\n" + print " * Animation / Physics Data (APData) Address: Unknown" +endfunction + +startfunction print_bone_group + getarray PADDING_OFFSET PADDING_OFFSETS_ARRAY i + searcharray IDX BONE_GROUPS_ARRAY PADDING_OFFSET + print "\n" + print " * Bone Group: %IDX%" +endfunction + +set BONES_STRING "* Bones: " +string BONES_STRING + BONES +print "%BONES_STRING%" + +# Get the bones group for the next step +if BONES != 0 + for i = 0 < BONES + getarray BONE BONES_ARRAY i + set PREV_BONE BONE + set NEXT i + math NEXT + 1 + if NEXT == BONES + set BONE SIZE + math BONE - 0x08 # So the padding to end value comes out correct; there's 8 bytes of additional padding at the end of each model + else + getarray BONE BONES_ARRAY NEXT + endif + callfunction get_bone_group 1 PREV_BONE BONE + next i +endif + +if BONES != 0 + print "\n" + print "* Located At:" + for i = 0 < BONES + getarray BONE BONES_ARRAY i + string B p "%x" BONE + print "\n" + print " * %i%: 0x%B%" + print "\n" + print " * Name: Unknown" + # Only call this for specific models; normal mobs and gimmicks don't really have this + if NAMESPACE == "Boss" | NAMESPACE == "Player" + callfunction print_bone_group 1 i + endif + callfunction print_vertex_data_location 1 BONE NAMESPACE + callfunction print_animation_location 1 BONE + next i +endif + +print "\n" +print "---" +print "\n" \ No newline at end of file