Author Topic: Yatta!!  (Read 14101 times)

phaeron

  • *
  • Posts: 30
    • View Profile
Yatta!!
« on: 2002-04-13 04:32:00 »
I figured out how Cloud's battle pose is stored... finally!

The battle pose is stored at the beginning of the 'rtda' resource, as a translation followed by Euler angles for each bone.  It took me a long time to figure out that the Euler angles are actually 36-bit, stored as three 12-bit binary rotation fractions (0x400 == 90 degrees).  The battle coordinate system is right handed, with X-Z being the ground plane, +Y being into the ground, and +Z ordinarily away from the enemies.  Rotation order is +Z axis, then +X axis, then +Y axis.

Anyway, in 'rtda':

00000010: 14 00 (unknown)
00000012: 56 03 (length of data for this chunk)
00000014: 00 00 (X translation)
00000016: 00 FE (Y translation)
00000018: 2E 00 (Z translation)
0000001A: 00 (unknown)
0000001B: 00 00 00 00 0_ (root locator: X 0d, Y 0d, Z 0d)
0000001F: _C 00 EC E0 00 (hip: X 270d, Y 333d, Z 0d)
00000024: F8 2F E5 E8 A_ (torso: X 349d, Y 358d, Z 327d)
00000028: _0 BB 0C 82 BC (head: X 16d, Y 17d, Z 62d)
...
00000083: _D 56 00 00 00 (right boot tip: X 300d, Y 0d, Z 0d)

I haven't figured out the rest of the data in the block, but with the above I have Cloud rendering in OpenGL in his base pose.  I suspect the rest of the block is the idle animation, but I haven't confirmed that yet.  Also, now that I know that the junk in 'rtab' isn't a bone mask, I'm beginning to suspect it is animation sequencing data.

phaeron

  • *
  • Posts: 30
    • View Profile
Yatta!!
« Reply #1 on: 2002-04-13 04:33:00 »
Alright, who's the wiseguy who entered in "famous programmer" as my tag?  :D

Sephiroth 3D

  • *
  • Posts: 1679
    • View Profile
    • ModCitizen 42
Yatta!!
« Reply #2 on: 2002-04-13 06:28:00 »
My guess is either Qhimm or Saint. Probably Qhimm.

But that's cool how you decoded the animation files. Bravo! I think Fice and Alhexx are gonna post a question or two, but it great that you finally broke that code for us. It should go much quicker now...

Sephiroth 3D

"I don't understand..." "You don't have to understand." - Final Fantasy: The Spirits Within

Sephiroth 3D.com
[email protected]

ShinRa Inc

  • *
  • Posts: 416
  • The Ascension of the Ordinary Man
    • View Profile
    • http://shinrainc.org
Yatta!!
« Reply #3 on: 2002-04-13 07:36:00 »
Quote
haven't figured out the rest of the data in the block, but with the above I have Cloud rendering in OpenGL in his base pose. I suspect the rest of the block is the idle animation, but I haven't confirmed that yet. Also, now that I know that the junk in 'rtab' isn't a bone mask, I'm beginning to suspect it is animation sequencing data.


Just to do my usual "state the probably obvious and not really needed to be said" bit, but wouldn't the __da files contain all of the sprites animations?  While the battle sprites are more complex than the field sprites, I would think they'd have fewer seperate animations (Especially the enemies), and where else would they be stored if not all in that file?


(Edit: ...On reading the post over again, I think I wasn't comprehending it entirely the first time {It's called a 0320 in the morning brain sprain :x}.  On reexamination, I think I've been able to interpet the i33+hax0r-speak as the following:
__da files are similar to .HRC files; basic skeletal assembly information, and possibly the default animation...Which makes sense, since the field sprites 'default animation' is just not moving?
__ab files are all of the animation sequences for the sprite, as if instead of a giant pool of .a files as in the fieldsprites, they took any and all animations for the sprite, and compressed / appended / whatever'd them into the single __ab file

...Am I anywhere near being right?  o.o)
[edited] 346 2002-04-13 08:44

phaeron

  • *
  • Posts: 30
    • View Profile
Yatta!!
« Reply #4 on: 2002-04-13 07:58:00 »
Skeletal information isn't stored in the '__da' file -- that is stored in '__aa'.  All that the '__da' file gives you is bone orientations.  I know that the '__da' file contains at least some of the battle animations -- the second packet is the critical HP animation.  I haven't been able to decode any of the animation frames or any animations past the first two.  I think the first two bytes in each animation are the frame count.  It's easier to look at the PSX animation files than the PC version's, because although the data is exactly the same, the PSX version has the animations individually indexed and the PC version doesn't.  Cloud has at least 40 battle animations.

The '__ab' file is still a mystery to me, but it does contain either decoding directions or pointers to animations, because patching the first table entry at 00000190 from 00 FE C0 to 01 FE C0 makes Cloud play his critical HP animation instead of his normal battle idle.

ShinRa Inc

  • *
  • Posts: 416
  • The Ascension of the Ordinary Man
    • View Profile
    • http://shinrainc.org
Yatta!!
« Reply #5 on: 2002-04-13 09:02:00 »
Heh...I'm still getting up to speed on all this stuff, so forgive my ocassional idiocy and/or stupidity.  :O  The Critical HP animation might be another "default" type thing....  What I mean is, unless a sprite is doing something, it has what I've been calling a "default" animation.  The enemies only have one...it doesn't change if they get critical HP or status effects, and if they die....they go away.

BUT, the main characters (except Sephiroth) would have three of these default, or more accurately "idle" animations.  A normal one, a Critial HP / Status effect, and when they're sprawled out dead on the floor.

Got some Ifalna questions, but that's probably better in a new thread...

ficedula

  • *
  • Posts: 2178
    • View Profile
    • http://www.ficedula.co.uk
Yatta!!
« Reply #6 on: 2002-04-13 09:55:00 »
Cool! Battle animations! I'll start looking at them tonight...

Incidentally: Skeletal information stored in the __aa files: has anyone decoded these? If they have, I missed that ;)

Alhexx

  • *
  • Posts: 1894
    • View Profile
    • http://www.alhexx.com
Yatta!!
« Reply #7 on: 2002-04-13 13:16:00 »
WOW ! Great work!
I think I'll have to work on Ultima and implement all that stuff!

As for the famous programmer: I guess it was Qhimm. That would be typical for Qhimm's humour... well, let's see: Moron, Level ?? ... :D

 - Alhexx

The SaiNt

  • *
  • Posts: 1300
    • View Profile
Yatta!!
« Reply #8 on: 2002-04-13 16:33:00 »
Excellent.
Btw, the title wasn't bestowed by me.
I don't go around doing things like that.

BTW, important note in FFR forum. FFR members, please give me a prompt reply.
[edited] 1 2002-04-13 17:39

phaeron

  • *
  • Posts: 30
    • View Profile
Yatta!!
« Reply #9 on: 2002-04-13 19:53:00 »
'rvaa' (Aeris' skeleton, PC style):

0000000C: 1F 00 00 00 (31 bones)

00000034: FF FF FF FF (hip: parent is root locator)
00000038: 00 00 A4 C2 (hip: bone length is -82.0F)
0000003C: 01 00 00 00 (??)

00000040: 00 00 00 00 (torso: parent is hip)
00000044: 00 00 01 C3 (torso: bone length is -129.0F)
00000048: 01 00 00 00 (??)

0000004C: 01 00 00 00 (head: parent is torso)
00000050: 00 00 AC C2 (head: bone length is -86.0F)
00000054: 01 00 00 00 (??)

You get the idea.  All bones are rotated by their transform; all children are rotated and translated.  The skeletons are constructed roughly the same as the field models, although Aeris has 4 bones in her pigtail here.   :laugh:

In case anyone is interested, the PSX skeleton format is similar, except that the bone records are composed of four 16-bit integers (8 bytes), in the order bone ID, length, data offset, bone length.  Same skeleton.

ficedula

  • *
  • Posts: 2178
    • View Profile
    • http://www.ficedula.co.uk
Yatta!!
« Reply #10 on: 2002-04-13 20:54:00 »
Right! That'll be a *big* help. Domo arigato! ^_^

* Goes off to program a battle model decoder...

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
Yatta!!
« Reply #11 on: 2002-04-13 21:52:00 »
phaeron: If you like, it can be changed to "infamous programmer". ^_^
But seriously, I sometimes use ranks as a means to clarify which board members actually have useful stuff to say. Feel free to pick your own rank though, I just wanted to get rid of the "newbie" label.

P.S. This offer does not apply to the rest of you lot. I choose which members can have special ranks, so don't anybody go bugging me about it.

ShinRa Inc

  • *
  • Posts: 416
  • The Ascension of the Ordinary Man
    • View Profile
    • http://shinrainc.org
Yatta!!
« Reply #12 on: 2002-04-14 02:14:00 »
Quote
P.S. This offer does not apply to the rest of you lot. I choose which members can have special ranks, so don't anybody go bugging me about it.


...Fiddlesticks.

Alhexx

  • *
  • Posts: 1894
    • View Profile
    • http://www.alhexx.com
Yatta!!
« Reply #13 on: 2002-04-14 09:00:00 »
Ah, hell, this means a lot of work for me now ... .p Plugin ... Ultima ... however, it's fine to see that there are some other people workin' on the model format (well, let's name the "people": phaeron )

However, I've got a lot of stuff to do right now, so don't expect any new releases within the next days...
(our old English teacher would say:
... as far as Ultima is concerned ... :D )

 - Alhexx

 - edit -
Qhimm: I'm absolutely satisfied with my Moderator / Freak rank :D
[edited] 169 2002-04-14 10:01

ficedula

  • *
  • Posts: 2178
    • View Profile
    • http://www.ficedula.co.uk
Yatta!!
« Reply #14 on: 2002-04-14 10:25:00 »
phaeron:
Quote

00000034: FF FF FF FF (hip: parent is root locator)
00000038: 00 00 A4 C2 (hip: bone length is -82.0F)
0000003C: 01 00 00 00 (??)

00000040: 00 00 00 00 (torso: parent is hip)
00000044: 00 00 01 C3 (torso: bone length is -129.0F)
00000048: 01 00 00 00 (??)

0000004C: 01 00 00 00 (head: parent is torso)
00000050: 00 00 AC C2 (head: bone length is -86.0F)
00000054: 01 00 00 00 (??)

As for the third value for each bone; either 1 or 0. Well, looking at Aeris' model, she has 31 bones, of which 23 are marked "1". Now, looking at the polygon files, there's 23 of them...

I'm sure you get what I'm saying ;)

(Edit: Corrected my counting ;) )
[edited] 68 2002-04-14 15:43

Alhexx

  • *
  • Posts: 1894
    • View Profile
    • http://www.alhexx.com
Yatta!!
« Reply #15 on: 2002-04-14 21:22:00 »
Since I had nothing interesting to do tonight, I started writing a Decode-Function for those 36-Bit Angles. I think my result is useful.
Here's the result:

Code: [Select]

int DeCodeAngle(unsigned char* pbyData, int nType, float *nXangle, float *nYangle, float *nZangle)
{
// Used to convert angles to degrees
// 1 Euler = 90 / 1024
const float fEuler = 0.087890625;
switch(nType)
{
case 0: // Decode first 36 Bits
*nXangle = float(((pbyData[0] << 4) | ((pbyData[1] & 0xF0) >> 4)) * fEuler);
*nYangle = float((((pbyData[1] & 0x0F) << 8 ) | ((pbyData[2]))) * fEuler);
*nZangle = float(((pbyData[3] << 4) | ((pbyData[4] & 0xF0) >> 4)) * fEuler);
return 0;
break;
case 1: // Decode last 36 Bits
*nXangle = float((((pbyData[0] & 0x0F) << 8 ) | ((pbyData[1]))) * fEuler);
*nYangle = float(((pbyData[2] << 4) | ((pbyData[3] & 0xF0) >> 4)) * fEuler);
*nZangle = float((((pbyData[3] & 0x0F) << 8 ) | ((pbyData[4]))) * fEuler);
return 0;
break;
default: // Illegal Value
return -1;
break;
}
}


If you want to try it out, create a Win32 Console Application under VC++ and replace the original code by the following one:

Code: [Select]

// AADAtest.cpp : Definiert den Einsprungpunkt für die Konsolenanwendung.
//

#include "stdafx.h"
#include <stdio.h>
#include <iostream.h>

int DeCodeAngle(unsigned char* pbyData, int nType, float *nXangle, float *nYangle, float *nZangle)
{
// Used to convert angles to degrees
// 1 Euler = 90 / 1024
const float fEuler = 0.087890625;
switch(nType)
{
case 0: // Decode first 36 Bits
*nXangle = float(((pbyData[0] << 4) | ((pbyData[1] & 0xF0) >> 4)) * fEuler);
*nYangle = float((((pbyData[1] & 0x0F) << 8 ) | ((pbyData[2]))) * fEuler);
*nZangle = float(((pbyData[3] << 4) | ((pbyData[4] & 0xF0) >> 4)) * fEuler);
return 0;
break;
case 1: // Decode last 36 Bits
*nXangle = float((((pbyData[0] & 0x0F) << 8 ) | ((pbyData[1]))) * fEuler);
*nYangle = float(((pbyData[2] << 4) | ((pbyData[3] & 0xF0) >> 4)) * fEuler);
*nZangle = float((((pbyData[3] & 0x0F) << 8 ) | ((pbyData[4]))) * fEuler);
return 0;
break;
default: // Illegal Value
return -1;
break;
}
}

int main(int argc, char* argv[])
{
// Declare and initialize vars
unsigned char byRData[9]; // 9 Bytes (72 Bits) -> Buffer:
// Angles for hip and torso (à 36 Bits)
unsigned char* pbyRData = &byRData[0]; // Pointer at Array
float X = 0, Y = 0, Z = 0; // Return Values

// Create file stream, open file and seek to 0x24
FILE* stream;
stream = fopen("C:/Dokumente und Einstellungen/Alhexx/Desktop/aa_da/rt__/rtda","rb");
fseek(stream, 0x24, 0);

// Read Data to Buffer
fread((char*)&byRData, 9, 1, stream);

// Deocde hip
DeCodeAngle(pbyRData, 0, &X, &Y, &Z);
cout << "hip Angles:n";
cout << "X: " << X << endl;
cout << "Y: " << Y << endl;
cout << "Z: " << Z << endl << endl;

// Decode torso
DeCodeAngle(pbyRData + 4, 1, &X, &Y, &Z);
cout << "torso Anglesn";
cout << "X: " << X << endl;
cout << "Y: " << Y << endl;
cout << "Z: " << Z << endl << endl;

//close file stream
fclose(stream);
return 0;
}

Important: Don't forget to change the filename in the fopen function !

 - Alhexx

 - edit -
Had to correct tabs in code... - and disable smilies !

 - edit 2 -
Hey, disabling smilies does not work   :x

[edited] 169 2002-04-14 22:28

phaeron

  • *
  • Posts: 30
    • View Profile
Yatta!!
« Reply #16 on: 2002-04-14 21:35:00 »
This is the code that I use:

Code: [Select]

class twelvebit_iterator {
protected:
const unsigned char *src;
bool half;
public:
twelvebit_iterator(const void *s) : src((const unsigned char *)s), half(false) {}

int operator*() const {
int v = (src[0]<<8) + src[1];

return half ? v&0xfff : v>>4;
}

twelvebit_iterator& operator++() {
++src;
if (half)
++src;

half = !half;
return *this;
}

twelvebit_iterator operator++(int) {
twelvebit_iterator it(*this);

++*this;

return it;
}
};

void FF7Model::loadPose(FF7Pack& pack, int pose_packet) {
const unsigned char *src = (const unsigned char *)pack[pose_packet].p + 11;
int nBones = mBones.size();

twelvebit_iterator it(src);

for(int i=0; i<nBones; ++i) {
int x = *it++;
int y = *it++;
int z = *it++;

mBones[i].setOrientation(Quaternion(Vector3(0,0,0), 1));
mBones[i].rotateXYZ(x, y, z);
}
}

ficedula

  • *
  • Posts: 2178
    • View Profile
    • http://www.ficedula.co.uk
Yatta!!
« Reply #17 on: 2002-04-14 21:38:00 »
And for the sake of completeness, here's mine ;)

Code: [Select]

function DecodeShittyAngles(Encoded: Int64; Partial: Boolean): TPoint3d;
function Angle: Single;
begin
If Partial then begin
Result := 360*( (((Encoded and $F) shl 8 ) or ((Encoded and $FF00) shr 8 ))/$FFF);
Encoded := Encoded shr 16;
end else begin
Result := 360*( (((Encoded and $FF) shl 4) or ((Encoded and $F00) shr 8 ))/$FFF);
Encoded := Encoded shr 8;
end;
Partial := Not Partial;
end;
begin
Result.X := Angle;
Result.Y := Angle;
Result.Z := Angle;
end;


Oh yeah, I've got everything working in *my* OpenGL testbed fine - but like you, I can only get the first two animation frames displaying. Bleh.
[edited] 68 2002-04-14 22:42

Darkness

  • *
  • Posts: 2181
    • View Profile
    • http://www.x0r.net
Yatta!!
« Reply #18 on: 2002-04-14 22:35:00 »
cant wait for the release of the program. :)

Sephiroth 3D

  • *
  • Posts: 1679
    • View Profile
    • ModCitizen 42
Yatta!!
« Reply #19 on: 2002-04-15 00:16:00 »
Here's my code:
Code: [Select]

Function ReadQhimmsForums()
    if ($username = Ficedula OR $username = Alhexx OR $username = phareon) then
         Copy $CodePost
         LaughAt $PeopleWhoTryToFigureOutTheDifferenceBetweenThe3Codes
         Use $CodePost Kefka
         Claim $NewFeature
         Thank $PersonITookTheCodeFrom
    Endif
End Function


At least that's what I'd like to say.

But if nothing else, it's cool to see our 3 best programmers go at it, each posting their own code for the same function! Keep it up guys!

Sephiroth 3D

"I don't understand..." "You don't have to understand." - Final Fantasy: The Spirits Within

Sephiroth 3D.com
[email protected]

Goku7

  • *
  • Posts: 1301
    • View Profile
Yatta!!
« Reply #20 on: 2002-04-15 01:52:00 »
Quote

On 2002-04-13 00:33, phaeron wrote:
Alright, who's the wiseguy who entered in "famous programmer" as my tag?  :D


LOL!!!!  :laugh:

But seriously, I think "Infamous Programmer" would have a higher comedy coefficient :wink:.

But that's enough of me trying to sound like I'm a heavy-duty programmer.  It is definitely neat to see several pieces fall into place in quick succession.

So, with this done, does this mean you can more or less give, say, Cloud, a totally new battle stance by entering the new X,Y, and Z positions for the bones, in that format?
[edited] 239 2002-04-15 02:53

phaeron

  • *
  • Posts: 30
    • View Profile
Yatta!!
« Reply #21 on: 2002-04-15 02:09:00 »
Almost.  All of the animation frames after the first appear to be stored as deltas, so you'll still get roughly the same fidgeting even with the new pose.  What you'll likely end up with, though, is a floating weapon since it doesn't seem to be attached to the hands like you'd expect.



ShinRa Inc

  • *
  • Posts: 416
  • The Ascension of the Ordinary Man
    • View Profile
    • http://shinrainc.org
Yatta!!
« Reply #22 on: 2002-04-15 05:11:00 »
For cloud, at least, the Weapon would *have* to be seperated from the hand, since he 'holsters' it on his back...and lets go, when he does magic / victory pose.

I don't think any of the other characters let go of their weapons, though.

Sephiroth 3D

  • *
  • Posts: 1679
    • View Profile
    • ModCitizen 42
Yatta!!
« Reply #23 on: 2002-04-15 05:58:00 »
Casting, correct, but in the finishing move, he never releases his hand. Casting is the one that has the seperate weapons. Otherwise, his hand is attached to the weapon model at all times. (His hand is part of the weapon model itself.)

Aeris lets go of her staffs when she casts magic or Limits.

Sephiroth 3D

"I don't understand..." "You don't have to understand." - Final Fantasy: The Spirits Within

Sephiroth 3D.com
[email protected]

ShinRa Inc

  • *
  • Posts: 416
  • The Ascension of the Ordinary Man
    • View Profile
    • http://shinrainc.org
Yatta!!
« Reply #24 on: 2002-04-15 08:24:00 »
Quote
(His hand is part of the weapon model itself.)

Uh...No it's not.  For most enemies, that's right (Rufus, MPs, etc), but for all of the "party" characters....and even some enemies (SOLDIERs, Reno) the weapons are definately seperate models from the hands.  I've been perusing for the various weaponry models in battle.lgp, so I'm as certain of this as I can be...

I haven't played the game in a while, so my memory is a bit fuzzy on some details (ie; cloud's victory dance).  Apologies.

Also...updated sprite graphic.  I *did* touch up the hair color in MSPaint this time (Since I can't get Ultima working...), but that was it.
http://members.aol.com/acaiitoarms/gren.jpg
I've got some other sprites done, too.  I may upload some shots of them tomorrow.