Engineer roocker666 Posted November 29 Engineer Share Posted November 29 (edited) Hi, we already have a Noesis plugin for SH4 Xbox characters(meshes and skeleton), thanks to Durik256 and alanm1: SH4 Xbox characters & skeleton So now I want to know if it is possible to extract animations too. I analyzed animations format and this is my research: Ok, first a reminder, .bin files have a main header. First 4 bytes of this header tells you the number files or parts and then pointers to each part, I am using henry01.bin, most of all pointers go to animations, just last 3 pointers go to mesh, textures and shadow. I cut the 1st animation to analyze it better: Edited November 29 by roocker666 1 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted November 29 Author Engineer Share Posted November 29 In some animations Table2(T2) are Floats, looks like 3 Floats of data and 1 Float padding. You can see this in animation number 2. Here is henry01.bin and the two first animations(I cut those from henry01.bin): henry01 I have zero knowledge about animation formats, lol. I just tried to understand the different blocks of SH4 animations. Thanks! Link to comment Share on other sites More sharing options...
Engineer shak-otay Posted November 30 Engineer Share Posted November 30 (edited) Well, looks to me like an unusual proceeding. Wouldn't you go for the bone count first, then check a simple animation for its frames per bone? edit: I see you found 29 pointers. Surprise... (== bone count) In the smd file created from Henry.bin using Durik256/alanm1's py script the rotations are all zero. No idea whether it's a SH4 feature or whether they need to be found. (Also it would be nice to have the real bone names instead of placeholders bone_[number].) bone_0 is 'root', the two "chains" starting at 12 and 17 are not fingers, seems, because there's left hand/right hand bones only? version 1 nodes 0 "bone_0" -1 1 "bone_1" 0 2 "bone_2" 1 3 "bone_3" 2 4 "bone_4" 3 5 "bone_5" 1 6 "bone_6" 5 7 "bone_7" 6 8 "bone_8" 0 9 "bone_9" 8 10 "bone_10" 9 11 "bone_11" 10 12 "bone_12" 9 13 "bone_13" 12 14 "bone_14" 13 15 "bone_15" 14 16 "bone_16" 15 17 "bone_17" 9 18 "bone_18" 17 19 "bone_19" 18 20 "bone_20" 19 21 "bone_21" 20 22 "bone_22" 4 23 "bone_23" 11 24 "bone_24" 7 25 "bone_25" 16 26 "bone_26" -1 27 "bone_27" -1 28 "bone_28" -1 29 "bone_29" -1 end skeleton time 0 0 0.000000 -219.022919 -2.569616 0.000000 -0.000000 0.000000 1 0.000000 0.000000 0.000000 0.000000 -0.000000 0.000000 2 18.000000 33.022919 -7.430384 0.000000 -0.000000 0.000000 3 0.000000 78.000000 -2.000000 0.000000 -0.000000 0.000000 4 0.000000 84.000000 -6.000000 0.000000 -0.000000 0.000000 5 -18.000000 33.022919 -7.430384 0.000000 -0.000000 0.000000 6 0.000000 78.000000 -2.000000 0.000000 -0.000000 0.000000 7 0.000000 84.000000 -6.000000 0.000000 -0.000000 0.000000 8 0.000000 0.000000 0.000000 0.000000 -0.000000 0.000000 9 0.000000 -40.977081 -5.430384 0.000000 -0.000000 0.000000 10 0.000000 -43.284210 -2.452426 0.000000 -0.000000 0.000000 11 0.000000 -13.832092 3.474270 0.000000 -0.000000 0.000000 12 10.000000 -30.000000 -4.000000 0.000000 -0.000000 0.000000 13 24.000000 6.000000 -4.000000 0.000000 -0.000000 0.000000 14 56.000000 0.000000 -2.000000 0.000000 -0.000000 0.000000 15 54.000000 0.000000 2.000000 0.000000 -0.000000 0.000000 16 0.000000 0.000000 0.000000 0.000000 -0.000000 0.000000 17 -10.000000 -30.000000 -4.000000 0.000000 -0.000000 0.000000 18 -24.000000 6.000000 -4.000000 0.000000 -0.000000 0.000000 19 -56.000000 0.000000 -2.000000 0.000000 -0.000000 0.000000 20 -54.000000 0.000000 2.000000 0.000000 -0.000000 0.000000 21 0.000000 0.000000 0.000000 0.000000 -0.000000 0.000000 22 1.000000 18.000000 22.000000 0.000000 -0.000000 0.000000 23 0.000000 -3.830841 -0.022519 0.000000 -0.000000 0.000000 24 -1.000000 18.000000 22.000000 0.000000 -0.000000 0.000000 25 17.274750 6.581696 1.481747 0.000000 -0.000000 0.000000 26 -18.000000 -24.000000 -18.000000 0.000000 -0.000000 0.000000 27 18.000000 -24.000000 -18.000000 0.000000 -0.000000 0.000000 28 -144.000000 -284.000000 -16.000000 0.000000 -0.000000 0.000000 29 144.000000 -284.000000 -16.000000 0.000000 -0.000000 0.000000 end Couldn't make sense of the pointers (to frame blocks?) Tried an offset (0x80) at no avail. Search for signature 010001FF gave 170 results and might help structuring the bin. (ok, you used it already - "animation ID") Edited November 30 by shak-otay 1 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted November 30 Author Engineer Share Posted November 30 Sadly there are no bone names. Henry's skeleton has no bones in fingers because it is a playable character but it has an extra bone in one hand(for weapons maybe. Check this screenshot). Yes, signature "010001FF" is the ID for animations so henry's file has 170 animations. Then each animation has two more signatures "030001FF"(don't know what this means, it has more bytes after this) and "020001FF"(pointers to frames?). We can search in SH4 E3 debug symbols, some .c files have structs about animations. For example this .c file: SH4 E3 sg_anime.c this has some structs, maybe for those signatures. In line 236 that struct matches with "frame header", I don't know about Table1(T1) but Table2(T2) looks like key frames(?) Those .c files are for PS2 but Xbox and PC have the same animation format. That animation folder has more .c files about animations, so maybe we can find some answers in those .c files. Link to comment Share on other sites More sharing options...
Engineer shak-otay Posted December 1 Engineer Share Posted December 1 (edited) Well, that c code is an information overkill for me. I'd start it simpler, here's an assumed animation curve of a bone: (integer list at 0x5AA0 with 27 values should be the time line, 4 values skipped, 4, 0C etc ) The 27 points at 0x5AE0 are floats. At 0xCAB0 a frame with 42 integer points (shorts): Still we don't know which frame blocks belong to which bones. I did a signature check (2 DWords): 1C 3C 58x 1C 4C 20x 1C 5C 13x 1C 6C 9x 1C 7C 3x 1C 8C 6x 1C 9C 2x 1C AC 2x 1C BC 5x 1C CC 2x ------------ 10 80 76x 10 90 61x ------------------ 14 44 9x 14 54 4x 14 74 7x 14 84 3x 14 A4 3x 14 B4 1x 14 D4 1x Sadly the sum of highest counts (58, 76, 61) exceeds 170, so I'm wrong here? (The DWord before those 2 DWs (1C000000 8C000000 for example) is the count of frame lines in the specific frame block. 0x35 = 53 decimal at 0x407B8.) edit: the high counts seem to be wrong because of uncomplete signature search: for 0000 10000000 80000000 there's 3 findings only. For 0000 1C000000 3C000000 still 58 results but 44 to be subtracted (DWord being 0) so 14 findings remain. Good. But not checked now... Edited December 1 by shak-otay 1 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 2 Author Engineer Share Posted December 2 According with this struct(which I think is "frame header"): struct _anon4 { short key_type; short reserved; short nb_keys; char skeleton_no; unsigned char relative; unsigned int time_table_offset; unsigned int keys_offset; }; first short "key_type"(unknow), 2nd short "reserved"(unknow2), 3rd short "nb_keys"(number of keys or count?), char "skeleton_no"(maybe bone number? ), char "relative"(unknow3), unsignet int "time_table_offset"(pointer to Table1), unsigned int "keys_offset"(pointer to Table2). So yes, maybe Table1 is time line(0x5AA0) and Table2 is key frames(0x5AE0 and 0xCAB0, these could be short or Float). I still don't know what are those bytes after 03 00 01 FF signature.. 1 Link to comment Share on other sites More sharing options...
Bigchillghost Posted December 3 Share Posted December 3 Just using simple check for tran/rot with the type flag (ignoring scenarios of different data types): (skel) (anim) 2 1 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 3 Author Engineer Share Posted December 3 Nice!, that is really cool man. Finally we are getting something, thanks! Link to comment Share on other sites More sharing options...
Sparagas Posted December 3 Share Posted December 3 4 hours ago, Bigchillghost said: Just using simple check for tran/rot with the type flag (ignoring scenarios of different data types): (skel) (anim) Can you make a light tutorial on how you did it, or at least the full animation layout code? Link to comment Share on other sites More sharing options...
Bigchillghost Posted December 4 Share Posted December 4 17 hours ago, Sparagas said: Can you make a light tutorial on how you did it, or at least the full animation layout code? For short, extract the skeleton with ASH, export it as *.end, then open the anim in ARC and import the *.end skeleton. Code the layout, hit the Compile button to check for any grammar mistakes; press the Execute button to execute the layout context. Pick the correct GUI options and press Convert to convert the read animation data. Then you're free to check the result with the Preview button. Layout for "henry01_1st_animation" (the original animated bone count is 1-off so there's a fix on it): seek address[0x10] long boneCnt calc boneCnt[+][1] seek address[0x48] begin loop[boneCnt] long offset calc offset[+][0x40] push offsetList[offset] end loop[boneCnt] begin loop[boneCnt] value offset[offsetList][boneIdx] seek address[offset] word type word skip word keyCnt word boneIndex long timeOffset long keyOffset calc timeOffset[+][offset] calc keyOffset[+][offset] test type[==][0x10] begin scope seek address[timeOffset] word tKeyIndex[keyCnt] seek address[keyOffset] begin loop[keyCnt] short Translation[4] end loop[keyCnt] end scope test type[==][0xD] begin scope seek address[timeOffset] word rKeyIndex[keyCnt] seek address[keyOffset] begin loop[keyCnt] short Rotation[4] end loop[keyCnt] end scope end loop[boneCnt] Have fun! 2 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 4 Author Engineer Share Posted December 4 (edited) On 12/3/2024 at 9:53 AM, Bigchillghost said: Just using simple check for tran/rot with the type flag (ignoring scenarios of different data types): OK, you used just two data types for tra/ro(x10, xD), analyzing more henry animations(and other characters) I found more: x1, x2, x4, x7. So why are different data types? Edited December 4 by roocker666 Link to comment Share on other sites More sharing options...
Bigchillghost Posted December 5 Share Posted December 5 6 hours ago, roocker666 said: I found more: x1, x2, x4, x7. So why are different data types? My guess, some of the bits indicate whether it's tran, rot or scal, the other bits stands for the actual data types and component count. You'll have to compare with different cases to find the rules. Or perhaps check the C code for any suspicious enum types. 1 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 5 Author Engineer Share Posted December 5 (edited) 19 hours ago, Bigchillghost said: My guess, some of the bits indicate whether it's tran, rot or scal, the other bits stands for the actual data types and component count. You'll have to compare with different cases to find the rules. Or perhaps check the C code for any suspicious enum types. I was checking in different C files but I did not found data types 😞 BUT on "Sparagas" Github there is a script for 010 made by "Hunter Stanton" this reads the whole animation code. Well, no all. ID "02 00 FF FF" has pointers to frames but for some reason there is no count for those pointers in animations, weird.. He also found data types but I am not sure if are correct. Here is if you want to take a look: sh4_pc_animation.bt Use this bt script on individual animations like "henry01_1st_animation" Oh, one more thing: You used 0x10 as bone count but I think that is incorrect, that is a pointer to ID "03 00 FF FF" Bone count only appears in mesh header not in animations. Henry bone count is "1E"(or 30 Dec), I analyzed more characters and in all animations 0x10 is always 1C so yes, it is a pointer to ID "03 00 FF FF" Edited December 5 by roocker666 Link to comment Share on other sites More sharing options...
Bigchillghost Posted December 8 Share Posted December 8 On 12/6/2024 at 4:52 AM, roocker666 said: Oh, one more thing: You used 0x10 as bone count but I think that is incorrect, that is a pointer to ID "03 00 FF FF" Bone count only appears in mesh header not in animations. I see. Will have to calculate the count manually in this case. On 12/5/2024 at 3:10 AM, roocker666 said: I found more: x1, x2, x4, x7. So why are different data types? What I can tell with some examinations: 1 float quat[4]; 2 float quat[4]; float quat2[4]; 4 float tran[4]; 7 float tran[4]; float tran2[4]; 0xD short quat[4]; 0x10 short tran[4]; For type 2 & 7 using the first key component the anim appeared to be shifted to a different origin, but the two anims seem identical: Code for anim 46 in henry01.bin (same GUI options): calc animBase[=][0x5EE80] seek address[animBase] byte skip[0x14] long hdrOffset calc hdrOffset[+][animBase] seek address[hdrOffset] long skip[2] calc curPos[=][0] tell address[curPos] long boneCnt calc boneCnt[-][0xC] calc boneCnt[/][4] seek address[curPos] begin loop[boneCnt] long offset assert offset[>][0] calc offset[+][hdrOffset] push offsetList[offset] end loop[boneCnt] begin loop[boneCnt] value offset[offsetList][boneIdx] seek address[offset] word type word skip word keyCnt word boneIndex long timeOffset long keyOffset calc timeOffset[+][offset] calc keyOffset[+][offset] typedef dataType[short] calc eleType[=][-1] // 0 = T, 1 = R calc skipSize[=][0] test type[==][1] begin scope typedef dataType[float] calc eleType[=][1] end scope test type[==][2] begin scope typedef dataType[float] calc eleType[=][1] calc skipSize[=][16] end scope test type[==][4] begin scope typedef dataType[float] calc eleType[=][0] end scope test type[==][7] begin scope typedef dataType[float] calc eleType[=][0] calc skipSize[=][16] end scope test type[==][0xD] calc eleType[=][1] test type[==][0x10] calc eleType[=][0] assert eleType[>=][0] // check for unmatched scenarios test eleType[==][0] begin scope seek address[timeOffset] word tKeyIndex[keyCnt] seek address[keyOffset] begin loop[keyCnt] byte skip[skipSize] dataType Translation[4] end loop[keyCnt] end scope test eleType[==][1] begin scope seek address[timeOffset] word rKeyIndex[keyCnt] seek address[keyOffset] begin loop[keyCnt] byte skip[skipSize] dataType Rotation[4] end loop[keyCnt] end scope end loop[boneCnt] 2 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 8 Author Engineer Share Posted December 8 19 hours ago, Bigchillghost said: Code for anim 46 in henry01.bin (same GUI options): Thanks man, I was testing more animation offsets and it seems to work! Just a little detail, last animation(at 0x139280 in henry01.bin) is when Henry dies but it looks different.. In the game he falls on his knees and dies but in ARC tool, the skeleton does not fall on its knees. Maybe this little glitch is present in more animations but it is hard to tell because we need to check every animation and there are A LOT, lol. Here is the comparison: 1 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 9 Author Engineer Share Posted December 9 (edited) By the way, here is other model "anmix_test.bin". It seems like it is a test model so it has only 2 animations. Main file header has 4 Pointesr: 0x80 mesh, 0x6DB00 textures, 0xB4E80 anim1, 0xBF200 anim2, Maybe it will be more easy, anim1 seems to look fine I guess but anim2 looks weird.. And I noticed that after ID "02 00 01 FF"(in animations) are 4 bytes 00 00 01 00, in Henry those 4 bytes are always 00 00 00 00. Probably it does not matter because you skip those. anmmix_test.rar Edited December 9 by roocker666 Link to comment Share on other sites More sharing options...
Bigchillghost Posted December 9 Share Posted December 9 (edited) 15 hours ago, roocker666 said: Just a little detail, last animation(at 0x139280 in henry01.bin) is when Henry dies but it looks different.. In the game he falls on his knees and dies but in ARC tool, the skeleton does not fall on its knees. There's no new type flags in this anim and the data seem to be converted correctly. From what I've checked, the knee bones are bone 3 and bone 6 and they both have 1 initial rotation key only. But bone 26 to 29 have more keys while they're all connected to the root bone. Either these bones somehow control other bones or there might be something related to inverse kinematics? Just wild guesses. By the way, the structure of the 03 00 01 FF chunk appears to be: long sig // 03 00 01 FF word parentLinkCnt word unkLinkCnt long linkOffset long linkSize for i = 0 < parentLinkCnt char boneId char parentId for i = 0 < unkLinkCnt char boneId // bone 26 to 29 char unkBoneId[3] I'd recommend to check the game logics with a decompiler for further process. Edited December 9 by Bigchillghost 1 Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 9 Author Engineer Share Posted December 9 3 hours ago, Bigchillghost said: There's no new type flags in this anim.. I see, I think I found other different data type in one of the models but I can't remember which one, lol. I will try to find it.. Oh, I forgot. I found 03 00 01 FF structs in C files! So your structure is correct 🙂 just some little differences: struct _anon1// 03 00 01 FF header { unsigned int type_id; short n_connects; short n_ik_chains; int connects_offset; int ik_chains_offset; }; struct _anon5// connects { unsigned char bone_no; char parent_no; }; struct _anon6//ik_chains { unsigned char handle_no; char ikhandle_type; char start_no; char effector_no; }; Link to comment Share on other sites More sharing options...
Bigchillghost Posted December 11 Share Posted December 11 Well, that make sense. There're 4 IK chains including two arms and two legs. But IK is a field that's a little bit advanced to me. And there doesn't seem to be any simple solution with FBX for such features. And the main purpose for ARC is to focus on simple key-frame animations. So you might have to ignore those glitchy anims for now. Link to comment Share on other sites More sharing options...
Engineer roocker666 Posted December 11 Author Engineer Share Posted December 11 5 hours ago, Bigchillghost said: But IK is a field that's a little bit advanced to me. And there doesn't seem to be any simple solution with FBX for such features. I understand, We can use those glitchy animations like that, don't worry. Thank you for your time and all the help man! Link to comment Share on other sites More sharing options...
Sparagas Posted December 14 Share Posted December 14 This is everything that is known about animation files written in the 010 Editor Binary Template. https://github.com/Sparagas/Silent-Hill/blob/main/010 Editor - Binary Templates/sh4_unnamed_animation.bt It is not perfect, but maybe it helps. Also, could someone suggest how to write it more clearly or rename some variables? 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now