Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.

Metal Gear Solid 5 (MGSV) animations

Featured Replies

  • Author
  • Localization

JohnHudeski, posted Thu Jun 15, 2017 5:55 am (24129)


omg that makes so much more sense

Values for a i have seen include
0x85 //very first guy (the 133-130 guy i spoke of)
0x6
0x80
0x3
0x0
0x83

It must mean a is a flag that gets Or'd

Thank you so much.
I don't think i could have understood that at all
  • Replies 83
  • Views 35
  • Created
  • Last Reply

Top Posters In This Topic

  • Author
  • Localization

JohnHudeski, posted Thu Jun 15, 2017 10:04 am (24132)


id-daemon wrote:
yes b is bits used
a has 0x80 bit indicating that its not last entry in the set, and other bits is track type,

0 - rotation
3 - position
5 - root rotation
6 - root position

i don't understand what do you mean about 130 bytes


are you sure it is

0 - rotation
3 - position
5 - root rotation
6 - root position

and not

0 - position
3 - rotation
5 - root position
6 - root rotation

?

Cos every entry that has a position bit has a b of 16
and every rotation has a 12 bits to read
  • Author
  • Localization

id-daemon, posted Thu Jun 15, 2017 3:10 pm (24134)


JohnHudeski wrote:
are you sure it is

0 - rotation
3 - position
5 - root rotation
6 - root position


yes i am
  • Author
  • Localization

JohnHudeski, posted Sat Jun 17, 2017 1:25 pm (24183)


I am 99% there.
I only have 2 questions I think.
it seems each track size is based on the bytes from the addr[n 1] -addr[n]
where addr is the offset address in each sub entry some magic number
when I divide the size by bits to read it always has a remainder
eg 140 / 12.
some files even have a smaller size than the bits to read.

How do you figure out the animation frame size/ length in seconds?

I can send you a sample file complete 010 template if interested (so you don't have to keep guessing at what I am describing lol)
  • Author
  • Localization

id-daemon, posted Sat Jun 17, 2017 1:43 pm (24184)


I'm not sure what reminder you're talking about, but

JohnHudeski wrote:
some files even have a smaller size than the bits to read.

this must NEVER happen.

Also, I never use 010 and have no idea about templates.
  • Author
  • Localization

JohnHudeski, posted Sat Jun 17, 2017 9:31 pm (24185)


This is sad and terrifying lol

Code:
//Gobals
local int counter = 0;

local int rootPos = 0;
local int rootRot = 0;
local int boneRot = 0;
local int bonePos = 0;

local int subEntAddr[60];


//Data type declaration

typedef struct(int arraySize)
{
    local int size = arraySize;
    byte array[arraySize];
}ByteArray;


string FlagReader(int flag)
{
    /*
    0 - rotation
    3 - position
    5 - root rotation
    6 - root position
    */
    local string s0;
    local int f = flag & ~0x80; //remove 0x80
    switch(f)
    {
    case 0x0:
        s0 = "rotation";
        boneRot = 1;
        break;
    case 0x3:
        s0 = "position";
        bonePos = 1;
        break;
    case 0x5:
        s0 = "Root_rot";
        rootRot = rootRot 1;
        break;
    case 0x6:
        s0 = "Root_pos";
        rootPos = rootPos 1;
        break;
    }
    local string s2;
    SPrintf(s2, " (0xx)",flag);
    return s0 s2; 
}

typedef struct
{
    local int currPosition = FTell();
    int addr; //Maybe 248
    short index; //references an index in based on size

    subEntAddr[index] = addr addrbac;

    ubyte typeFlag; //this is an enum flag bit
    ubyte bitSz< bgcolor=cYellow>;
   
    //debug
    Printf("\n    d) Addr: %d ( %d: %d)\n    ----------------------------", index, addr,currPosition, addr currPosition);
   
    Printf("\n    %s", FlagReader(typeFlag));
    Printf("\n    typeFlag: 0xx, bitSz: 0xx\n", typeFlag, bitSz);
}SubEntry;

typedef struct
{
    Printf("\n\nEntryx[%d]:\n{", counter);
    counter = 1;
    uint _hash;
    byte subCount; //int
    short unkn;
    byte pad;
    if(subCount > 4)
    {
        SubEntry sEntry;
    }
    else
    {
        SubEntry sEntry[subCount];
    }
}Entryx;

//Generic container?
typedef struct
{
    int hash;
    int a; //size a?
    int fileSize;
    // b[2] = number of files?
    int b[5];
    int hash2;

    //c[0] = //size b?
    //c[5] = motion headr size (skip char name)
    int c[11];
    //size of header = size a size b
}MainHdr;

typedef struct
{
    char sig[16];
    int64 hash_;
    int a,b;
    int size;
    int unkn;
    int __[6];

}MotionHdr;


//Actual entry
MainHdr mHdr;
MotionHdr mothdr;

struct Motion
{
    int entryCount; //defonitley
    int subEntryCount; //subEntryCount is another count (refereneced by entry) Bones?
    int a; //hash
    int b; //header size for this motion struct
    int c; 
    int entryAddr[entryCount]; //definitley
    local int i = 0;
    local int sum = 0;
    for(i =0; i < 60; i)
    {
        subEntAddr[i] = -1;
    }
    subEntAddr[subEntryCount] = FileSize();

    int pad[4];

    //byte data[sum 16];
    for(i = 0; i < entryCount; i )
    {
        Entryx dataX;
        Printf("}\n");
    }

    local int j = 0;
    local int addrOff = FTell() - dataX[0].sEntry[0].addr;
    local int idx =0;
    for(i = 0; i < subEntryCount; i )
    {
        Printf("\n%d - %d : %d",subEntAddr[i],subEntAddr[i 1], subEntAddr[i 1]-subEntAddr[i]);
        ByteArray bArr(subEntAddr[i 1]-subEntAddr[i]);
    }
}motion;

Printf("\n\nTrackStats: %d rootPosition(s), %d rootRotation(s), %d bonePos(s), %d boneRot(s)", rootPos, rootRot, bonePos, boneRot);

  • Author
  • Localization

id-daemon, posted Sun Jun 18, 2017 7:46 pm (24203)


JohnHudeski wrote:
This is sad and terrifying lol


Yes, good luck with this. I never understood why people are doing this. It only complicates things.
  • Author
  • Localization

JohnHudeski, posted Sun Jun 18, 2017 10:59 pm (24210)


I moved to c#
  • Author
  • Localization

JohnHudeski, posted Tue Jun 20, 2017 3:21 pm (24219)


:D

I think I might have figured out my error
Bits size/Bits to read != bytes
I always thought it was bytes for some reason

so all the 6's i saw were bytes and not bits.
I finally understand what you meant by variable bits
cos 6 bytes = 48 bits
divided by 12 you 4 floating points (typical rotation size)
divide by 14 you get 3 floating points (typical position size)
I am so dumb

i'd just like to know.
Is this animated at 60fps?
How do you know what frame each Vector/quaternion belongs to?
I don't think normalizing and stretching them all to fit the maximum frame length them all is a particularly good idea
Would also wreck animation quality
  • Author
  • Localization

id-daemon, posted Tue Jun 20, 2017 3:48 pm (24220)


JohnHudeski wrote:
:D

you are only in the beginning of the way ;)

JohnHudeski wrote:
divided by 12 you 4 floating points (typical rotation size)


they are not floating points, they are integers

JohnHudeski wrote:
How do you know what frame each Vector/quaternion belongs to?


Between the data there is a frame count for each value. It's always 8 bits.
  • Author
  • Localization

JohnHudeski, posted Tue Jun 20, 2017 4:36 pm (24222)


id-daemon wrote:
you are only in the beginning of the way ;)

LMAO

id-daemon wrote:
they are not floating points, they are integers

Integers/Bits that you convert to floats?

id-daemon wrote:
Between the data there is a frame count for each value. It's always 8 bits.

Between the actual quaternion and vector data?
I knew this was too easy
  • Author
  • Localization

id-daemon, posted Tue Jun 20, 2017 4:50 pm (24223)


JohnHudeski wrote:
Integers/Bits that you convert to floats?

yes
  • Author
  • Localization

JohnHudeski, posted Tue Jun 20, 2017 5:10 pm (24224)


id-daemon wrote:
JohnHudeski wrote:
Integers/Bits that you convert to floats?

yes

That's what I meant
but how do you figure out what frame a specific Vector belongs to
like what time cos not all bones have the same number of frames

I think this is my last hurdle. I figured out the bone mapping (in my head)
  • Author
  • Localization

Zuppermati, posted Sun Oct 15, 2017 3:02 pm (27338)


Hi me again. I had some freetime and I used it to do a quick hack on your tool. Can I ask you why did you force us to use snake's model? Cause all I can see it's used for except for reading a couple of values is to read block 66 which from what i got is the number of bones in the model. By changing the model required into the one needed (eg: for loading lisa's animations i used och0_main0_def.fmdl, for reedus I used pla0_main0_def.fmdl etc) you get the correct animation (for example in lisa's animations there are bones only on his left eye since the right one is "gouged out"). If I used snake's model it would load it like snake (so the bone structure would be much different and giving me incorrect results). So... can I ask you the reason?
  • Author
  • Localization

id-daemon, posted Sun Oct 15, 2017 4:00 pm (27341)


Zuppermati wrote:
Can I ask you why did you force us to use snake's model? Cause all I can see it's used for except for reading a couple of values


It read the WHOLE skeleton (all bones with their names, structure and positions) from model file. Skeleton is needed for animations. I used snake's skeleton because I thought all skeletons are the same.
  • Author
  • Localization

Zuppermati, posted Sun Oct 15, 2017 4:27 pm (27342)


They're not actually.

https://imgur.com/a/wAs7G

On the left you have lisa's animation unpacked with snake's model and on the right with her model. You can see how the scale is corrected and it has a more coherent bone structure (you can see how she's missing the right eye bones as i told you).
Reedus is pretty much the same as it has a different chest structure for his jacket.
I didn't attach ik to arms and legs to cut some time but anyway till you use them "as is" (without attaching a model on it) they beheave pretty much the same. But if you do attach lisa's model to it blender goes a bit of WTF.

It still won't unpack me the baby and refrigerator's animations even if I do use them (it gives me a strange exception and I'm not good with understanding how reverse engineering animations works) but every animation it could unpack with snake's model can be unpacked with corrected bones if you use the proper models.

If we take off the part about reading the skeleton which I've shown you it can work without snake's model are there any other reasons you used it for?
  • Author
  • Localization

id-daemon, posted Sun Oct 15, 2017 6:48 pm (27347)


Zuppermati wrote:
But if you do attach lisa's model to it blender goes a bit of WTF.


Ok, thats right. Since I never had any human models other than Snake, I couldn't check it.
baby and refrigerator (no idea what this is) probably have different RIG, not only different skeleton.

Zuppermati wrote:
If we take off the part about reading the skeleton which I've shown you it can work without snake's model are there any other reasons you used it for?


I don't remember. By "take off the part" you mean you will read the skeleton yourself somehow? Because without reading the skeleton animation will not work.
  • Author
  • Localization

Zuppermati, posted Sun Oct 15, 2017 7:08 pm (27348)


id-daemon wrote:
baby and refrigerator (no idea what this is) probably have different RIG, not only different skeleton.

Well I remember I saw on your youtube channel your work on the fetus so you probably know better than me how does it work :lol: . Exactly what did you do to make the program work with it?

id-daemon wrote:
I don't remember. By "take off the part" you mean you will read the skeleton yourself somehow? Because without reading the skeleton animation will not work.

Sorry I used the wrong term. For "take off the part" i meant "excluding using it to read the skeleton (which as I told you even other models can do the job so PT hackers like me won't have to disassemble mgsv just to get a damned fmdl :) ) and block 66, is it used for anything else I didn't see?
  • Author
  • Localization

id-daemon, posted Mon Oct 16, 2017 3:55 pm (27364)


Zuppermati wrote:
Sorry I used the wrong term. For "take off the part" i meant "excluding using it to read the skeleton (which as I told you even other models can do the job so PT hackers like me won't have to disassemble mgsv just to get a damned fmdl :) ) and block 66, is it used for anything else I didn't see?


I don't understand. If you don't read the skeleton, you cannot extract animations. And what is block 66 ?
  • Author
  • Localization

Zuppermati, posted Tue Oct 17, 2017 11:48 am (27376)


Again you're misunderstanding what I'm saying let's try again:
"is the filestream used in the program to read snake's model used to do anything else in the program except to read the whole model (which other fmdl can do)?"

id-daemon wrote:
And what is block 66 ?


Line 100 of mgs5_gz_human.cs:

Code:
fileStream.Seek(66L, SeekOrigin.Begin);


Reads the byte in position 66 which is the number of bones in the model
  • Author
  • Localization

id-daemon, posted Tue Oct 17, 2017 7:28 pm (27387)


Zuppermati wrote:
is the filestream used in the program to read snake's model used to do anything else in the program


No, its only used to read the skeleton and bone names.
  • Author
  • Localization

Zuppermati, posted Sat Oct 21, 2017 10:02 am (27504)


Oook then I made a fairly dumb human tool hack which easily allows to load both model and fmdl (so if you want to apply, let's say, snake's animations to quiet, it can be done too by using quiet's model and snake's fmdl and it should give better results). Will share once my campus restores internet :'(

Btw which process did you use to attach the bones to a model? Cause simple automatic weighting in blender or skin modifier in 3ds max gives horrible results. Did you weight every single bone manually? That would be crazy
  • Author
  • Localization

id-daemon, posted Sat Oct 21, 2017 10:50 am (27508)


Again I have no idea what are you talking about.

1 fmdl IS a model. What do you call a model then?

2 you could easily extract quiet animations with my original tool, just renaming quiet fmdl to snake's fmdl name, and it should work fine, and not "better" as you do by making incorrect combine of different models.

3 of course i was not doing anything manually. Models are weighted already, why do you need redoing this?
  • Author
  • Localization

JohnHudeski, posted Sun Oct 22, 2017 5:35 am (27582)


After 1 year i fully understand this dumb animation format
My only questions is why does the animation file contain more bones than the skeleton?
In your program you hard coded the IK bones
How did you even know those were ik bones?
  • Author
  • Localization

id-daemon, posted Sun Oct 22, 2017 6:36 am (27584)


As I said before:

id-daemon wrote:
Also important note, in this game animation tracks are NOT per-bone. They are per IK group. And each group has a number of tracks for it, which is not equal to number of bones in it. Some bones may have no tracks at all, some may have many.

I mean, human animation file does NOT contain any bones. It only contains tracks for RIG groups.
This information (about groups) is contained in .FRIG files

On the other hand, simple animations, like rats, and fetus from PT, they are like normal animations, and they contain tracks for bones.
Guest
This topic is now closed to further replies.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.