Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!
You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!
@structpointers( 24, {
0:'_pass', # string
8:'_texture',
12:'_pass', # (A,D,S color data)
20:'_pass', }) # unknown (not documented) (detected by pathfinder in KAR)
def _material(offset,_apply=True):
Tcll return to us.
Notes of animation files (pl**aj.dat)
Every animation in the file is formatted as its own dat file in a way and the next animation dat header is on the next line directly after the end of the previous animation.
There seems to be only 1 root node and its entry in the string table is the name of the animation.
The root node - General animation info
0x00 - unknown (possible int for number of animations (always 0x00000001)
0x04 - unknown (always 0x00000000)
0x08- frame count (float: the character will go on to the next animation as soon as this is over. If it is greater the character will just freeze until then)
0x0C- pointer to bone index table (no idea what to call this)
0x10- animation info
bone index table (0x1*number of bones- length)
The number of bones can be gotten by just counting up the bones in the pl**.dat or looking at the joint matanim section and counting those up.
0x1- number of sections (possibly animations). Bone index is given by the position from the start of the table.
Terminated by 0xFF
animation info (0x0C*(total number of sections in the bone index table)-length)
0x00- length of animation data (0x02 bytes)
0x04- unknown (my speculation is that it works like the animation format word in the chr0 file for the brawl format)
0x0C- pointer to animation data
This is as far as my ability to pattern recognize goes. Anything more would require I actually know what Im talking about and have any idea how animations work to confirm.
As far as my assumption about the animation data format. I believe the format is encoded in the bits like in the chr0 files. However the bits would be reversed, and melee bone transformations are ordered by rotation, scale, translation whereas brawls is ordered by scale, rotation, translation.
Considering writing a code to basically record the transformations of a particular animation every frame and just export the ram. But I wouldn't even know what to do with that.
Your observations on joint counts are correct (at least in my findings so far).Some interesting features of this pointed data are:
- it is far too small to be animation data for any of the characters, even if it's compressed somehow
- It is replicated between animations, but at different offsets
- it does not look like floating point data or offsets. If anything the alternating zeroes make me think it is a series of chars / uint8_ts, but it doesn't look like a string in any character encoding I'm familiar with.
Regardless, I'm pretty sure it's some kind of animation metadata, NOT actual animation data.
EDIT: SOMETHING I DIDN'T REALIZE WHEN I MADE THIS POST
It's probably bone-specific flags.
Pichu has 45 bones and his char[] is 44 elements long.
Pikachu has 52 bones and his char[] is 52 elements long.
Mewtwo has 67 bones and his char[] is 68 elements long.
Ganon has 83 bones and his char[] is 84 elements long
If you ignore flags on the grounded bottom-ecb bone (bone 0) and possibly the other ecb bones (vertical and horizontal ecb bones), these numbers work out very nicely.
struct FIGATREE_DATA
{
// 0x00
uint32 unknown0x00;
uint32 unknown0x04;
float unknown0x08;
uint32 trackCountsOffset <format = hex>;
// 0x10
uint32 trackInfoOffset <format = hex>;
local uint32 jointCount = 0;
if (trackCountsOffset != 0)
{
PushFP();
FSeekOfs(trackCountsOffset);
// determine number of joint entries
while (ReadUByte(FTell() + jointCount) != 0xFF) ++jointCount;
uint8 jointTrackCounts[jointCount];
PopFP();
}
if (trackInfoOffset != 0 && jointCount > 0)
{
PushFP();
FSeekOfs(trackInfoOffset);
local uint32 jointNum = 0;
struct
{
for (jointNum = 0; jointNum < jointCount; ++jointNum)
{
struct
{
struct TRACK_INFO
{
uint16 dataSize;
uint16 unknown0x02 <format = hex>;
uint32 dataFlags <format = hex>;
uint32 dataOffset <format = hex>;
PushFP();
FSeekOfs(dataOffset);
uint8 trackData[dataSize];
PopFP();
} jointTrackInfo[jointTrackCounts[jointNum]] <optimize = false>;
} jointTrackInfo;
}
} jointTrackInfo;
PopFP();
}
};
That IDA plugin gave me a stiffie, not gonna lie.Given the current simplicity observed i am a little sad it took me this long to get around to looking into it, but on the other hand it has shown me that proper tools are very helpful to accomplishing a task efficiently (possibly more on this later, but enterprising dolphin debuggers and reverse engineers looking to improve their debugging user experience might find some interestingly useful repositories on github under a username suspiciously similar to my own, heh).
lol. i would say that this is the response of a true debugging enthusiast, but that might be admitting too much...That IDA plugin gave me a stiffie, not gonna lie.
This will lead to support for animations in any eventual tools, but as far as being able to extract mesh, texture, skeleton, and skinning information from .dat files has been possible for a while (at least the information to do so has been available).So, is this going to lead to a tool that can extract models from the .dat files with their weighting onto PC? We have 'em for Brawl, and even Smash WiiU, and Melee's going to be 15 this year, so it kinda should have one too.
Would you mind tagging up a release of the plugin on your Github? Compiling it myself will probably be a PITA.lol. i would say that this is the response of a true debugging enthusiast, but that might be admitting too much...
...Anyway, yes, being able to debug with proper support for comments, structures, code flow graphs, cross references, etc. is extremely useful.
/* ReadDolphinMap.idc
Loads Dolphin .map files into IDA Pro.
Carl Kenner, 2014
*/
#include <idc.idc>
static main(void)
{
auto fh;
auto fname;
auto pusha, popa;
auto start, end;
auto success;
auto count;
auto line;
auto ea; // column 1
auto name; // column 30
auto p;
auto code;
fname = AskFile(0,"*.map","Load a .map file from Dolphin emulator...");
fh = fopen(fname, "r");
if (fh == 0) {
Message("Can't open %s\n", fname);
return;
}
Message("Loading %s dolphin map file:\n", fname);
for (count = 0; 1; count++) {
line = readstr(fh);
if (line == -1)
break;
if (strlen(line)>30 && line[0]!=" ") {
ea = xtol(substr(line,0,8));
name = substr(line,29,strlen(line)-1);
if (substr(name,0,3)!="zz_") {
if (!MakeNameEx(ea,name,SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO |SN_NOWARN)) {
MakeNameEx(ea,name+"_2",SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO );
}
Message("ea='%x', name='%s'\n", ea, name);
} else {
MakeNameEx(ea,name,SN_NOCHECK | SN_PUBLIC | SN_AUTO | SN_WEAK | SN_NOWARN);
}
} else if (strlen(line)>30) {
ea = xtol(substr(line,18,18+8));
p = strstr(line, " \t");
if (p>=30 && ea!=0) {
name = substr(line,30,p);
code = substr(line,p+2,strlen(line));
SetFunctionCmt(ea, code, 0);
if (!MakeNameEx(ea,name,SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO |SN_NOWARN)) {
MakeNameEx(ea,name+"_2",SN_NOCHECK | SN_PUBLIC | SN_NON_AUTO );
}
}
}
}
Message("Dolphin map file done.\n");
}
Ok, i will see what i can do.Would you mind tagging up a release of the plugin on your Github? Compiling it myself will probably be a PITA.
Dolphin has a GDBStub. If you fixed it up to not be ****, they'd probably take it.Ok, i will see what i can do.
Will require my fork of dolphin as well currently. Hopefully i can clean up the additions at some point and get it merged into master, but not sure that will happen.
So to clarify, Is this how you're saying the data is laid out?The data is mainly a list of keyframe "commands" structured as:
"command": 4-bit command/interpolation type, or'ed with keyframe count (up to 16-bits; continue reading bytes as long as the current byte has 0x80 set, + 1)
Then for "keyframe count" times, depending on the "command" value:
either read a value, read a tangent, or read both a value and tangent
- the data format structuring from my previous post are used here to read the specified sized value/tangent (as little endian)
followed by reading a keyframe duration value (up to 16-bits; continue reading bytes as long as the current byte has 0x80 set)
00 06 00 00 06 85 88 00 00 00 00 00
11 B0 AE 03 B0 00
struct keyframe
{
int interpolation_type;
float duration;
float value;
float tangent;
};
The main reason I asked is that, while I know that Tcll is working on something similar, I've kinda given up hope on him actually getting something out that works fully for this title. Every time he gets close, he scraps everything he has and starts fresh.[A]s far as being able to extract mesh, texture, skeleton, and skinning information from .dat files has been possible for a while (at least the information to do so has been available).
[snip]
[G]ood things come to those who wait.
Will see what can be done.
Im not sure why this is an animation and model workshop but the stuff in this thread looks solely to be cracking animations so it shouldnt really help you for what you want.The main reason I asked is that, while I know that Tcll is working on something similar, I've kinda given up hope on him actually getting something out that works fully for this title. Every time he gets close, he scraps everything he has and starts fresh.
To illustrate what I mean, I have the most recent release of his tool, which only outputs to .obj, and it was released in 2013, going by the Last Modified date on the files. That's why I'm putting my hopes on this project.
Looks good so far, though i think you may have a small bug. The 03 byte for the second keyframe shown, is part of the duration value of the first keyframe, so the next value byte should actually be B0 again with the next duration byte being 0.@revl8n
Thank you for the detailed description! It really helped clarify some things.
...
I've got my thing printing out all the keyframes of every track for an animation right now, and it seems to be going all right. I think all that's really needed to start experimenting with an exporter now is the meaning of the interpolation-type flag. I'll spend some time playing around with different values in the future, but this is finals season for me so I probably shouldn't be doing too much with it right now.
// command : interpolation type
1 - read value : step
2 - read value : linear
3 - read value : hermite
4 - read value and tangent : hermite
5 - read tangent : hermite
6 - read value : constant
// data formats (little endian)
0x00 - float (no scale)
0x20 - s16
0x40 - u16
0x60 - s8
0x80 - u8