Jump to content

MM 3D - Model Format discussion


Twili
 Share

Recommended Posts

No problem, that link was more or less just for reference for the rest of the thread. I figured the original code would be more difficult to compile - like with the usage of the Boost library in util.cpp, tho I never used that lib before (and it appears to only be used for some path handling there...?) - so a simple, standalone C version is nice to have.

Link to comment
Share on other sites

So, I discovered that it's incredibly easy to dump games via Gateway's Launcher.dat and generate xorpads to decrypt them via another homebrew Launcher.dat and took some pics and a video to celebrate.  ^_^

 

Shown is the dumping of Majora's Mask 3D...

 

pnsfezy.jpg

 

2vG8GBy.jpg

 

  • Like 1
Link to comment
Share on other sites

And here's a GAR extractor I wrote in C.

#include <stdio.h>

int main(int argc, char **argv)
{
    FILE *gar, *out;
    unsigned int files,len,off,path,sizes,y;
    unsigned short count,x;
    char longname[97], shortname[65], check=1;
    gar=fopen(argv[1],"rb");
    fseek(gar,0xA,SEEK_SET);
    count=(unsigned short)(fgetc(gar)|(fgetc(gar)<<8));
    fseek(gar,4,SEEK_CUR);
    sizes=(unsigned int)(fgetc(gar)|(fgetc(gar)<<8)|(fgetc(gar)<<16)|(fgetc(gar)<<24));
    files=(unsigned int)(fgetc(gar)|(fgetc(gar)<<8)|(fgetc(gar)<<16)|(fgetc(gar)<<24));
    for(x=0;x<count;x+=1)
    {
        fseek(gar,files+4*x,SEEK_SET);
        off=(unsigned int)(fgetc(gar)|(fgetc(gar)<<8)|(fgetc(gar)<<16)|(fgetc(gar)<<24));
        fseek(gar,sizes+12*x,SEEK_SET);
        len=(unsigned int)(fgetc(gar)|(fgetc(gar)<<8)|(fgetc(gar)<<16)|(fgetc(gar)<<24));
        fseek(gar,4,SEEK_CUR);
        path=(unsigned int)(fgetc(gar)|(fgetc(gar)<<8)|(fgetc(gar)<<16)|(fgetc(gar)<<24));
        fseek(gar,path,SEEK_SET);
        while(check!=0){check=fgetc(gar);}
        while(check!=0x2F)
        {
            fseek(gar,-2,SEEK_CUR);
            check=fgetc(gar);
        }
        fgets(shortname,65,gar);
        fseek(gar,path,SEEK_SET);
        fgets(longname,97,gar);
        out=fopen(shortname,"wb");
        printf("Extracting file %d...\n%s\n",x,longname);
        fseek(gar,off,SEEK_SET);
        for(y=0;y<len;y+=1){fputc(fgetc(gar),out);}
        fclose(out);
    }
    return 0;
}

  • Like 1
Link to comment
Share on other sites

  • 1 month later...
xdan, here's my latest notes on animations:

 

Any sample values provided are as they appear in little endian. This also focuses on the MM3D spec, which is a tad different than the OoT3D one, just like model data.

 

CTR Skeletal Animation Binary (*.csab)

 

0x0: magic "csab"

0x4: file size (u32)

0x8: version (u32, 05000000 = MM3D) (OoT3D is 03000000)

0xC: always 00000000? (u32)

0x10: 3 unknown floats?

0x1C: always 01000000? (u32)

0x20: animation node (anod) base (u32)

0x24: padding

0x34: frame count, minus 1 (u32)

0x38: unknown property (u32, seen 01000000 and 00000000)

0x3C: anod count (u32)

0x40: bone count (u32)

 

 

0x44: bone table (2*bone count in size)

 

Contains signed shorts (16-bit), if set to -1 (FFFF) the bone has no anod, else is the anod number for the bone.

2 bytes of padding after if the bone count is odd-numbered.

 

 

0x(varies): anod table (4*anod count in size)

 

Immediately after the bone table (+padding noted above), contains relative u32 pointers (to the anod base) to each anod.

 

 

anod:

 

0x0: magic "anod"

0x4: property 1 (u16, if set to 0000, the anod is empty, AKA same as a bone not having an anod. Weird.)

0x6: property 2 (u16, unknown purpose)

 

0x8: transformation table

 

Contains 6 u16 pointers, relative to the start of the anod:

 

+0x0: X rotations

+0x2: Y rotations

+0x4: Z rotations

+0x6: X translations

+0x8: Y translations

+0xA: Z translations

 

If any of these are set to 0, the transformation is locked. (0 for all frames)

 

0x14: 8 bytes of padding

 

 

Rotation/translation data:

 

+0x0: unknown property (u16)

+0x2: unknown property (u16)

+0x4: unknown float

+0x8: unknown float

+0xC: rotation/translation for each frame (u16) (rotations need to be converted to degrees the same way as N64 Zeldas)

 

 

Hope something comes of this! I want some kind of video or GIF demonstrating an animation if this works, even if it's just the skeleton.  ;)

 

Also, any of Link's animations have a larger bone table than he has bones, for some reason. More research will be needed for Link's special case.

  • Like 1
Link to comment
Share on other sites

 Share

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.