What's new

Melee Arcive Viewer (MAV) in development project.

revel8n

New member
.x files for directx support animations in both text and binary formats. can also look into smd which seems popular. but i can't really say. One of the things i plan on looking into is a better way of handling export to other format. Given i am a programmer and not an artist it has never really been that high on my priority list, but i want to change that for things like the tools i will release eventually.


TyPikachu - 0x6AB8

Code:
00 00 00 09 00 00 00 03 00 00 00 01 00 00 00 03
0B 00 00 06 00 00 00 00 00 00 00 0A 00 00 00 03
00 00 00 00 00 00 00 03 0E 00 00 06 00 00 2C E0
00 00 00 0D 00 00 00 03 00 00 00 01 00 00 00 03
0C 00 00 04 00 00 5A 60 00 00 00 FF 00 00 00 02
00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00

i'll try and take the time to color code this a little later if the explanation doesn not help.

The above hex block is a portion of the display list vertex format and attribute information. Each structure within the list is 0x18 bytes in length. It is structured like so:

Code:
// vertex declaration and attribute information
// attr, type, cnt, data_type, flags?, file_offset
struct VERTEX_DESCFMT
{
	// 0x00
	uint32 attr0x00;   // vertex attribute
	uint32 attrType0x04; // vertex attribute type
	uint32 compCount0x08; // vertex component count
	uint32 compType0x0C; // vertex component type
	// 0x10
	uint32 unknown0x10;
	uint32 dataOffset0x14 <format = hex>; // data offset
};


The list is terminate when the attr0x00 value is equal to 0x000000FF.

There are other values which you may be able to find by looking up gamecube programming documentation, but some of the main ones of interest are:

0x0 = Position Normal Matrix Index
0x9 = Position
0xA = Normals
0xD = Texture Coordinate 0

This value determines whether or not a particular value is even present as vertex data. As mentioned before, the position element is the only one required every time. The values should appear in the order expected, but for all intents and purposed you should be able to sort the attr value from lowest to highest for correct ordering and usage. Thus a position element will always be assumed to come before a normal element, and those always before texture coordinate elements.

The attribute type can be:

0 = None
1 = Direct
2 = 8-bit index
3 = 16-bit index

None and Direct designation mean the values are not indexed, and thus do not have an index value present in the display list (0x9800, etc. data).

The component count gives and indication of the size of the data element based on whether it contain x, y, and z..or just x and y values for example. It will usually be 0 or 1:

0 = Pos_XY, Norm_XYZ, Color_RGB, Tex_S
1 = PosXYZ, Color_RGBA, Tex_ST

So you should be able to match how the values are structured within the data.

The component type tells the actual size of each value within a structure and other information about the type:

0 = U8, RGB565
1 = S8, RGB8
2 = U16, RGBX8
3 = S16, RGBA4
4 = F32, RGBA6
5 = RGBA8

With U = unsigned, S = signed, F = float, and the numbers being the bit size.

So as an example:
Code:
00 00 00 09 00 00 00 03 00 00 00 01 00 00 00 03

Would give:
attr = 9
attrType = 3
compCnt = 1
compType = 3

which is:
position (9), 16-bit index (3), xyz (1), signed short (3)

So vertex data (deduced from this being position data) represents the vertex position stored with xyz components as signed short values, thus 6-bytes per vertex, 2-bytes per component, and the index value in the display list will be 16-bit.

From this information you should be able to gather everything you need to determine the sizes of things in the file.

Hopefully this will be helpful in the mean time. i hope to finish with the rest of the structures in this file format soon.

Big thanks to breakpoint for his help, as it allowed me get past a roadblock in understanding some of the things in the format (silly pointer relocation table). Hope to be able to share more soon as i clarify my findings and clean everything up. Wish me luck, heh.
 
OP
Tcll

Tcll

Complexity == Fun >:3
o_O text animations...
that file is a win for me.
 
collada would probably be better, but I don't really fell like typing all that extra code D:
x3d is also good... IDK if it supports animations however
 
but yea... I looked at a DXirectX animation (ascii) file and I was pleased :)
so I'm using dx format.
 
as for the data... I understood most of it, but there were a few parts that wern't very descriptive though...
don't feel bad, I do the same thing... XD
 
 
and that vetex part kinda threw me off a little bit...
 
I wan't to export to multiple formats too
just wan't to use something simple at the moment...
 
I will eventually work my way up to 3DS
But I also wan't to try the .blend format
 
I do learn quick..., it's just that it's a slow process in getting me to understand it...
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
alright guys...

it seems I've just hit a large bump...
I guess the dat files are a little more complicated than I thought. :(

I'm gonna have to put this project on hold for a little bit...

I will be working on an mdl0 importer for blender,
which will then advance to a pac importer.

once I get these done.., all I'll have to do is mod the code a little for melee.
I'll work on the dat importer first, and advance that up to MAV.

just to let you know my plans :p

sorry about the holdup however... :(
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
hmm... seems I was looking at the player hex wrongly...
here is the way it should be:

80 00 0C
09 04 2C 03 A7 05 8C
0C 07 D6 07 A8 05 8C
0C 07 D7 07 A9 05 8D
09 04 2E 03 A9 05 8D
09 04 2E 03 A9 05 8D
09 04 2D 03 A8 04 ED
03 07 83 07 37 04 F4
03 07 84 07 38 05 8D
03 07 84 07 38 04 F4
03 07 70 07 17 05 8C
09 04 2C 03 A7 05 8D
09 04 2E 03 A9 05 8D

?? vertex normal UV

I've imported a few more faces in my old pl converter since I've noticed this...
still... not all though...
 
Last edited:

revel8n

New member
As i mentioned previously this extra byte will usually be the position/normal matrix index. It references the joint matrix in the mesh that is used to position the vertex during rendering. The vertex format information i mentioned earlier also tells you which components are actually present and where the data for them is located.
 

Milun

New member
Ok, after much trial and error, I still can't get my C++ version of the code working. I've decided to do something useful, and research the Pl**Aj.dat files for Animations and joints.

However, for the sake of my curiosity, what could I have done wrong Tcll?

All my program does, is searches for the nearest occurrence of '98', '90' etc. to the offset point, reads the third hex which sais how many lines there are, then converts the said amount of lines, and repeats the process. This works well in some sections, but the others it returns giant values. It isn't really that important, I just want to know what I did wrong. Thanks in advance.

Oh, and I'm going to research Captain Falcons Aj file.
 
OP
Tcll

Tcll

Complexity == Fun >:3
hey Milun...
this may help you out on understanding the faces:
faces.zip: Download

it's more of a visual description...
(the way I learn)

sorry I didn't put alot of typing into this...
I really just made this.

but this is how the face data is supposed to work.
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
As i mentioned previously this extra byte will usually be the position/normal matrix index. It references the joint matrix in the mesh that is used to position the vertex during rendering.

OH...

so it's basically a VGroup index right??
 

revel8n

New member
However, for the sake of my curiosity, what could I have done wrong Tcll?

All my program does, is searches for the nearest occurrence of '98', '90' etc. to the offset point, reads the third hex which sais how many lines there are, then converts the said amount of lines, and repeats the process. This works well in some sections, but the others it returns giant values. It isn't really that important, I just want to know what I did wrong. Thanks in advance.

i mentioned in the post regarding the python code earlier that for a brute force method you cannot search for just a 0x98 byte or even 0x9800 value within the file to determine a matching display list section. This is because 0x9800 is a valid 16-bit value even outside of being the designator for a display list block. You need to pick a bigger pattern to compare against, which is why i used 0x00009800. Once you have a more consistent match for the beginning then you can be more sure that you are actually in the section you think you are and start using a tighter form for the match and ending conditions. i havent seen your code, but if you are getting values like one version of the pythin code was you are more than likely matching 0x98, 0x90, etc. that also appear often withing vertex and image data as well and thus will not follow the proper pattern for a display list.



@Tcll:
The extra byte i am referring to is an index value that tells which of the joint matrix values (associated with the bones used in the skeleton of the mesh when animated). The vertex values are transformed by the specified matrix before being rendered. This is why portions of things like the head of some characters appear on the ground by the characters feet. The joint matrices would have translated the vertices into the correct locations once they are applied.



i hope to have some things finished soon. At which point i will more than likely need some help from anyone interested in testing various values to see what they affect in the game so that their purpose can be determined. If it continues to take too long, i guess i will post a simplified template for 010 Editor that should help those currently doing manual hacking a great deal in finding the hex offsets and other information they need. Hopefully that should be good until i can put together a better viewer.

What other things are those interested in Melee looking to know about the formats?
 

Milun

New member
The vertex values are transformed by the specified matrix before being rendered. This is why portions of things like the head of some characters appear on the ground by the characters feet. The joint matrices would have translated the vertices into the correct locations once they are applied.

Now that is interesting. I hope we can decipher the bone data, because we'll finally be able to unscramble those pesky character models. I've converted a few Pl files with my... somewhat progressed model extractor, and I'd recommend using Jigglypuff as our first test. All her body parts are separate from her main body (I don't know how to explain it too well; her arm and leg vertices aren't connected to her body with faces).

I think I get what you mean with the '00009800' search. I'll see if If it works. Thanks.
 
OP
Tcll

Tcll

Complexity == Fun >:3
@ revel8n:

how would I go about applying the data??
maybe an equation or something easy for me to understand...

@ Milun:

that's exactly what revel8n did with mine.
I didn't know that's what you ment... :(

but I'm thanking revel right now.
I couldn't have gotton a working 'ty' mesh convertor without his help.
thanks revel8n :)

as for the bone data stuff...
you'd probably be better off working with Kirby.
reason being... he's more simple than Jigg.
(yes he has many forms..., but those are separate)
 
Last edited:

Myuutsuu

forever.
I was going to recommend taking a peek into Kirby as well. From some prior messing around experience in Brawl, he's really about as simple as you can get... But, if you [Milun] feel more confident on cracking Jiggs, feel free; it's sometimes best to stick to your guns with one character before moving onto others.

Good to hear there has been a little bit of progression since last page... Keep it up, all, this is looking real' good. :)
 

Milun

New member
The main reason I chose Jiggs over Kirby is because Kirby has a large mouth, which morphs his body quite a bit. I doubt that's important, but Kirby is still kind of difficult for me, because when I opened one of his hats (Pikachu) in my vertex extractor, it was still scrambled, implying he either has a new set of bones for each hat, or his main one incorporates them all (I can't remember if I saw any Kirby cap Aj files in GC Tool, I'll have to check back on that).
 

Myuutsuu

forever.
Last I checked, the only hats that alter Kirby himself (and being separate hats altogether) are Kirby hats Mewtwo, Jigglypuff, DK, and Falco. All the other caps have their bones, but do not require an altering to Kirby. I could be wrong; it's been a while since I've looked through Kirby stuff myself.
 

Milun

New member
Well, no news on the bone data (all I managed to accomplish is crashing the game... woopy). However, I have fixed my C++ program... converter... thingy© :D Not really important, but it will speed up my personal work.

you probably know this, but Aj files are really nice, in the sense that they actually give you headers in plain English before an animation, such as:

Code:
PlyPurin5K_Share_ACTION_Wait_figatree

I'm pretty sure there's some nice hex underneath it, but I haven't gotten any fun results.
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
umm... that's not a header...

it's the bottom of that particular file...
--it's basically many files in one.

that's why I'm calling it an archive.
I just don't know what that file format would be...
(something similar to the chr0 file of course)

what you gave there...
(Jiggs standing animation)

everything above that is the data for it.

EDIT: maybe I should start deciphering the data...
I might get better results...
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
here is a header for an AJ file:
00 00 1D EF 00 00 1B EC 00 00 00 6D 00 00 00 01
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

just another 32 byte header...

I at least have gotton more advanced to know that every 4 bytes contains needed info to offsets...
but that's about all I know.
 
OP
Tcll

Tcll

Complexity == Fun >:3
I did manage to find 1 thing:
not sure what it is though... but
Code:
[FONT=Lucida Console]43 34 00 00 00 00 1B [/FONT]
[FONT=Lucida Console]A8 00 00 16 [/FONT]
[FONT=Lucida Console]A4 00 00 16 [/FONT]
[FONT=Lucida Console]AC 00 00 16 [/FONT]
[FONT=Lucida Console]B8 00 00 16 [/FONT]
[FONT=Lucida Console]C4 00 00 16 [/FONT]
[FONT=Lucida Console]D0 00 00 16 [/FONT]
[FONT=Lucida Console]DC 00 00 16 [/FONT]
[FONT=Lucida Console]E8 00 00 16 [/FONT]
[FONT=Lucida Console]F4 00 00 17 [/FONT]
[FONT=Lucida Console]00 00 00 17 [/FONT]
[FONT=Lucida Console]0C 00 00 17 [/FONT]
[FONT=Lucida Console]18 00 00 17 [/FONT]
[FONT=Lucida Console]24 00 00 17 [/FONT]
[FONT=Lucida Console]30 00 00 17 [/FONT]
[FONT=Lucida Console]3C 00 00 17 [/FONT]
[FONT=Lucida Console]48 00 00 17 [/FONT]
[FONT=Lucida Console]54 00 00 17 [/FONT]
[FONT=Lucida Console]60 00 00 17 [/FONT]
[FONT=Lucida Console]6C 00 00 17 [/FONT]
[FONT=Lucida Console]78 00 00 17 [/FONT]
[FONT=Lucida Console]84 00 00 17 [/FONT]
[FONT=Lucida Console]90 00 00 17 [/FONT]
[FONT=Lucida Console]9C 00 00 17 [/FONT]
[FONT=Lucida Console]A8 00 00 17 [/FONT]
[FONT=Lucida Console]B4 00 00 17 [/FONT]
[FONT=Lucida Console]C0 00 00 17 [/FONT]
[FONT=Lucida Console]CC 00 00 17 [/FONT]
[FONT=Lucida Console]D8 00 00 17 [/FONT]
[FONT=Lucida Console]E4 00 00 17 [/FONT]
[FONT=Lucida Console]F0 00 00 17 [/FONT]
[FONT=Lucida Console]FC 00 00 18 [/FONT]
[FONT=Lucida Console]08 00 00 18 [/FONT]
[FONT=Lucida Console]14 00 00 18 [/FONT]
[FONT=Lucida Console]20 00 00 18 [/FONT]
[FONT=Lucida Console]2C 00 00 18 [/FONT]
[FONT=Lucida Console]38 00 00 18 [/FONT]
[FONT=Lucida Console]44 00 00 18 [/FONT]
[FONT=Lucida Console]50 00 00 18 [/FONT]
[FONT=Lucida Console]5C 00 00 18 [/FONT]
[FONT=Lucida Console]68 00 00 18 [/FONT]
[FONT=Lucida Console]74 00 00 18 [/FONT]
[FONT=Lucida Console]80 00 00 18 [/FONT]
[FONT=Lucida Console]8C 00 00 18 [/FONT]
[FONT=Lucida Console]98 00 00 18 [/FONT]
[FONT=Lucida Console]A4 00 00 18 [/FONT]
[FONT=Lucida Console]B0 00 00 18 [/FONT]
[FONT=Lucida Console]BC 00 00 18 [/FONT]
[FONT=Lucida Console]C8 00 00 18 [/FONT]
[FONT=Lucida Console]D4 00 00 18 [/FONT]
[FONT=Lucida Console]E0 00 00 18 [/FONT]
[FONT=Lucida Console]EC 00 00 18 [/FONT]
[FONT=Lucida Console]F8 00 00 19 [/FONT]
[FONT=Lucida Console]04 00 00 19 [/FONT]
[FONT=Lucida Console]10 00 00 19 [/FONT]
[FONT=Lucida Console]1C 00 00 19 [/FONT]
[FONT=Lucida Console]28 00 00 19 [/FONT]
[FONT=Lucida Console]34 00 00 19 [/FONT]
[FONT=Lucida Console]40 00 00 19 [/FONT]
[FONT=Lucida Console]4C 00 00 19 [/FONT]
[FONT=Lucida Console]58 00 00 19 [/FONT]
[FONT=Lucida Console]64 00 00 19 [/FONT]
[FONT=Lucida Console]70 00 00 19 [/FONT]
[FONT=Lucida Console]7C 00 00 19 [/FONT]
[FONT=Lucida Console]88 00 00 19 [/FONT]
[FONT=Lucida Console]94 00 00 19 [/FONT]
[FONT=Lucida Console]A0 00 00 19 [/FONT]
[FONT=Lucida Console]AC 00 00 19 [/FONT]
[FONT=Lucida Console]B8 00 00 19 [/FONT]
[FONT=Lucida Console]C4 00 00 19 [/FONT]
[FONT=Lucida Console]D0 00 00 19 [/FONT]
[FONT=Lucida Console]DC 00 00 19 [/FONT]
[FONT=Lucida Console]E8 00 00 19 [/FONT]
[FONT=Lucida Console]F4 00 00 1A [/FONT]
[FONT=Lucida Console]00 00 00 1A [/FONT]
[FONT=Lucida Console]0C 00 00 1A [/FONT]
[FONT=Lucida Console]18 00 00 1A [/FONT]
[FONT=Lucida Console]24 00 00 1A [/FONT]
[FONT=Lucida Console]30 00 00 1A [/FONT]
[FONT=Lucida Console]3C 00 00 1A [/FONT]
[FONT=Lucida Console]48 00 00 1A [/FONT]
[FONT=Lucida Console]54 00 00 1A [/FONT]
[FONT=Lucida Console]60 00 00 1A [/FONT]
[FONT=Lucida Console]6C 00 00 1A [/FONT]
[FONT=Lucida Console]78 00 00 1A [/FONT]
[FONT=Lucida Console]84 00 00 1A [/FONT]
[FONT=Lucida Console]90 00 00 1A [/FONT]
[FONT=Lucida Console]9C 00 00 1A [/FONT]
[FONT=Lucida Console]A8 00 00 1A [/FONT]
[FONT=Lucida Console]B4 00 00 1A [/FONT]
[FONT=Lucida Console]C0 00 00 1A [/FONT]
[FONT=Lucida Console]CC 00 00 1A [/FONT]
[FONT=Lucida Console]D8 00 00 1A [/FONT]
[FONT=Lucida Console]E4 00 00 1A [/FONT]
[FONT=Lucida Console]F0 00 00 1A [/FONT]
[FONT=Lucida Console]FC 00 00 1B [/FONT]
[FONT=Lucida Console]08 00 00 1B [/FONT]
[FONT=Lucida Console]14 00 00 1B [/FONT]
[FONT=Lucida Console]20 00 00 1B [/FONT]
[FONT=Lucida Console]2C 00 00 1B [/FONT]
[FONT=Lucida Console]38 00 00 1B [/FONT]
[FONT=Lucida Console]44 00 00 1B [/FONT]
[FONT=Lucida Console]50 00 00 1B [/FONT]
[FONT=Lucida Console]5C 00 00 1B [/FONT]
[FONT=Lucida Console]68 00 00 1B [/FONT]
[FONT=Lucida Console]74 00 00 1B [/FONT]
[FONT=Lucida Console]80 00 00 1B [/FONT]
[FONT=Lucida Console]8C 00 00 1B [/FONT]
[FONT=Lucida Console]98 00 00 1B [/FONT]
[FONT=Lucida Console]A4 00 00 1B [/FONT]
[FONT=Lucida Console]E4 00 00 1B [/FONT]
[FONT=Lucida Console]E8 00 00 1B [/FONT]
[FONT=Lucida Console]D8 00 00 00 00[/FONT]

it may not be in the right format..., but it's just a find.
 

revel8n

New member
Simple DAT Template

The header format for all .dat files is the same 32 byte structure i mentioned earlier in the thread. The 'Aj' files actually contain multiple dat files as you mentioned (al .dat files are technically already archive files themselves). Each file within the 'Aj' files are actually referenced from within the main Pl??.dat file, along with the file sizes, etc.

Haven't gotten to looking into these yet as i am still doing the main file, so i will let you know when i find out more. If you haven't figured out anything more before then.

Edit:
Silly thing still won't allow me to attach files....*sigh*.

Well here is the code for a simple Dat file template that will show you where all the offset locations are and a few bits of other information. i have removed some of the main structure information as it is not universal to all dat file. i will be posting another version soon with information on the Ty and Mesh related Pl files. But for those that just need an easier time finding offsets to data this should be very helpful as it is what i use to reverse things. Hope it helps. (They are for 010 Editor (www.sweetscape.com) for those that don't know.

common-types.bt:
Code:
/*****************************************************************************
 * common-types.bt - Common type definition used in binary formats.
 *
 *****************************************************************************
 * Revision History:
 *  2009/03/16 - GWC - Original
 *  2009/03/18 - GWC - Added type parsing functions
 */

typedef byte int8;
typedef ubyte uint8;

typedef union
{
	int8 v[4];
	struct
	{
		int8 x, y, z, w;
	} vec4;
} byte4 <read=byte4Read, write=byte4Write>;

typedef union
{
	uint8 v[4];
	struct
	{
		uint8 x, y, z, w;
	} vec4;
} ubyte4 <read=ubyte4Read, write=ubyte4Write>;

typedef union
{
	int16 v[2];
	struct
	{
		int16 x, y;
	} vec2;
} short2 <read=short2Read, write=short2Write>;

typedef union
{
	int16 v[3];
	struct
	{
		int16 x, y, z;
	} vec3;
} short3 <read=short3Read, write=short3Write>;

typedef union
{
	int16 v[4];
	struct
	{
		int16 x, y, z, w;
	} vec4;
} short4 <read=short4Read, write=short4Write>;

typedef union
{
	float v[2];
	struct
	{
		float x, y;
	} vec2;
} float2 <read=float2Read, write=float2Write>;

typedef union
{
	float v[3];
	struct
	{
		float x, y, z;
	} vec3;
} float3 <read=float3Read, write=float3Write>;

typedef union
{
	float v[4];
	struct
	{
		float x, y, z, w;
	} vec4;
} float4 <read=float4Read, write=float4Write>;

typedef struct
{
	union
	{
		float v[4];
		float2 rows[2];
	} vec2x2;
} float2x2;

typedef struct
{
	union
	{
		float v[6];
		float3 rows[2];
	} vec2x3;
} float2x3;

typedef struct
{
	union
	{
		float v[9];
		float3 rows[3];
	} vec3x3;
} float3x3;

typedef struct
{
	union
	{
		float v[12];
		float3 rows[4];
	} vec4x3;
} float4x3;

typedef struct
{
	union
	{
		float v[8];
		float4 rows[2];
	} vec2x4;
} float2x4;

typedef struct
{
	union
	{
		float v[12];
		float4 rows[3];
	} vec3x4;
} float3x4;

typedef struct
{
	union
	{
		float v[16];
		float4 rows[4];
	} vec4x4;
} float4x4;


// byte4 parsing functions
string byte4Read( const byte4 &v )
{
	local int32 t[4] = {v.v[0], v.v[1], v.v[2], v.v[3]};
	string s;   
	SPrintf( s, "(%6d, %6d, %6d, %6d)", t[0], t[1], t[2], t[3] );
	return s;
}

void byte4Write( byte4 &v, string s )
{
	SScanf( s, "(%d, %d, %d, %d)", v.v[0], v.v[1], v.v[2], v.v[3] );
}

// ubyte4 parsing functions
string ubyte4Read( const ubyte4 &v )
{
	string s;   
	SPrintf( s, "(%4u, %4u, %4u, %4u)", v.v[0], v.v[1], v.v[2], v.v[3] );
	return s;
}

void ubyte4Write( ubyte4 &v, string s )
{
	SScanf( s, "(%u, %u, %u, %u)", v.v[0], v.v[1], v.v[2], v.v[3] );
}

// short2 parsing functions
string short2Read( const short2 &v )
{
	local int32 t[2] = {v.v[0], v.v[1]};
	string s;   
	SPrintf( s, "(%6d, %6d)", t[0], t[1] );
	return s;
}

void short2Write( short2 &v, string s )
{
	SScanf( s, "(%d, %d)", v.v[0], v.v[1] );
}

// short3 parsing functions
string short3Read( const short3 &v )
{
	local int32 t[3] = {v.v[0], v.v[1], v.v[2]};
	string s;   
	SPrintf( s, "(%6d, %6d, %6d)", t[0], t[1], t[2] );
	return s;
}

void short3Write( short3 &v, string s )
{
	SScanf( s, "(%d, %d, %d)", v.v[0], v.v[1], v.v[2] );
}

// short4 parsing functions
string short4Read( const short4 &v )
{
	local int32 t[4] = {v.v[0], v.v[1], v.v[2], v.v[3]};
	string s;   
	SPrintf( s, "(%6d, %6d, %6d, %6d)", t[0], t[1], t[2], t[3] );
	return s;
}

void short4Write( short4 &v, string s )
{
	SScanf( s, "(%d, %d, %d, %d)", v.v[0], v.v[1], v.v[2], v.v[3] );
}

// float2 parsing functions
string float2Read( const float2 &v )
{
	string s;   
	SPrintf( s, "(%14f, %14f)", v.v[0], v.v[1] );
	return s;
}

void float2Write( float2 &v, string s )
{
	SScanf( s, "(%f, %f)", v.v[0], v.v[1] );
}

// float3 parsing functions
string float3Read( const float3 &v )
{
	string s;   
	SPrintf( s, "(%14f, %14f, %14f)", v.v[0], v.v[1], v.v[2] );
	return s;
}

void float3Write( float3 &v, string s )
{
	SScanf( s, "(%f, %f, %f)", v.v[0], v.v[1], v.v[2] );
}

// float4 parsing functions
string float4Read( const float4 &v )
{
	string s;   
	SPrintf( s, "(%14f, %14f, %14f, %14f)", v.v[0], v.v[1], v.v[2], v.v[3] );
	return s;
}

void float4Write( float4 &v, string s )
{
	SScanf( s, "(%f, %f, %f, %f)", v.v[0], v.v[1], v.v[2], v.v[3] );
}

DATTemplate.bt:
Code:
/*****************************************************************************
 * dat.bt - Structure definitions for Super Smash Brothers Melee - dat file related entities.
 *
 *****************************************************************************
 * Revision History:
 *  2009/09/29 - revel8n - Original
 *  2010/02/22 - revel8n - Changes based on information from breakpoint
 *  2010/02/22 - revel8n - More structure updates
 *  2010/02/23 - revel8n - Started adding other structures (FIGHTER and FIGATREE)
 */

#include "common-types.bt"

SetReadOnly(true);

// #pragma displayname("dat structures")
// #pragma fileextensions(".dat")

// #pragma byteorder(big_endian)
BigEndian();

// mark used bytes with a light green background

local int64 filePos = FTell();

// DAT_FILE File Structure
struct DAT_FILE
{
//	#pragma lockAt(0x00000000)

	// DAT_HEADER - DAT file header information structure
	SetBackColor(cLtGreen);
	struct DAT_HEADER
	{
		// 0x00
		uint32 fileSize0x00                 <format = hex>;
		uint32 dataBlockSize0x04            <format = hex>; // size of main data block
		uint32 relocationTableCount0x08;                    // unknown data size / 4
		uint32 rootCount0x0C;                               // unknown data size / 8
		// if combined "data sizes" + 0x20 is less than file size, then offset to string table?
		// overwritten data addresses (as such, assumed they are unimportant?)
		// - 0x20 - start + 0x20?
		// - 0x24 - start + dataBlockSize0x04 + 0x20 - offsets to offsets?
		// - 0x28 - start + [0x24] + (relocationTableCount0x08 * 4)
		// - 0x2C - start + [0x28] + (jobjCount0x0C * 8)
		// - 0x30 - start + [0x2C] + (unknown0x10 * 8)
		// - 0x3C - or'ed with 0x01
		// - 0x40 - start
		// 0x10
		uint32 unknown0x10; // unknown data size / 8
		uint32 unknown0x14; // '001B' in main Pl*.dat files
		uint32 unknown0x18;
		uint32 unknown0x1C;
	} fileHeader;
	
	if (0 != fileHeader.dataBlockSize0x04 &&
		0 < fileHeader.relocationTableCount0x08)
	{
		FSeek(0x20 + fileHeader.dataBlockSize0x04);
		SetBackColor(cLtGreen);
		uint32 relocationTable[fileHeader.relocationTableCount0x08] <format = hex>;
		
		local uint32 offsetNum = 0;
			
		filePos = FTell();
		
		FSeek(0x20 + fileHeader.dataBlockSize0x04);
		SetBackColor(cLtRed);
		struct
		{
			for (offsetNum = 0; offsetNum < fileHeader.relocationTableCount0x08; ++offsetNum)
			{
				FSeek(0x20 + relocationTable[offsetNum]);
				uint32 mappedOffsets <format = hex>;
			}
			FSeek(filePos);
		} relocatedOffsets;
		
		FSeek(0x20 + fileHeader.dataBlockSize0x04);
		SetBackColor(cLtBlue);
		struct
		{
			for (offsetNum = 0; offsetNum < fileHeader.relocationTableCount0x08; ++offsetNum)
			{
				//FSeek(0x20 + ReadUInt(0x20 + relocationTable[offsetNum]));
				FSeek(0x20 + relocatedOffsets.mappedOffsets[offsetNum]);
				uint16 mappedData <format = hex>;
			}
			FSeek(filePos);
		} relocatedData;
	}
	
	if (0 < fileHeader.rootCount0x0C)
	{
		FSeek(0x20 + fileHeader.dataBlockSize0x04 + (fileHeader.relocationTableCount0x08 * 4));
		SetBackColor(cLtRed);
		struct
		{
			struct
			{
				uint32 rootOffset0x00 <format = hex>;
				uint32 stringTableOffset0x04 <format = hex>; // offset to name string?
				
				filePos = FTell();
				FSeek(0x20 + rootOffset0x00);
				SetBackColor(cLtBlue);
				uint16 mappedData <format = hex>;
				FSeek(filePos);
			} rootNodes[fileHeader.rootCount0x0C] <optimize = false>;
		} rootNodes;
	}
	
	if (0 < fileHeader.unknown0x10)
	{
		FSeek(0x20 + fileHeader.dataBlockSize0x04 + (fileHeader.relocationTableCount0x08 * 4) + (fileHeader.rootCount0x0C * 8));
		SetBackColor(cLtBlue);
		struct
		{
			uint32 unknown0x00;
			uint32 unknown0x04;
		} unknownData0x10[fileHeader.unknown0x10];
	}
	
	// string table data
	if (0 < fileHeader.rootCount0x0C)
	{
		FSeek(0x20 + fileHeader.dataBlockSize0x04 + (fileHeader.relocationTableCount0x08 * 4) + (fileHeader.rootCount0x0C * 8) + (fileHeader.unknown0x10 * 8));
		SetBackColor(cLtYellow);
		struct
		{
			struct
			{
				string nodeName0x00;
			} stringTable[fileHeader.rootCount0x0C] <optimize = false>;
		} stringTable;
	}	
};

struct DAT_FILE fileInfo;
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
hmm...
archives containing archives...
similar to brres containing more brres files.

thanx

I'm trying out the 010 templates now.

EDIT: so how does the relocation table work??

and thanx again:
I now almost know how the header works.

I'm going with your way of using the header to find out the size and the value offsets, and then working it from there.

I'm definatly giong to look more into those AJ files...
now that you told me they're archives within archives.

EDIT2: Wait a minute...
DUH!!! (FACEPALM)

the relocation table is what lists the offsets to everything,
plus the size of all the offsets...

but still:
Which one's which??
and how do I go about converting the values??
(especially for offsets (offset size would probably be just a simple hex to decimal conversion))
 
Last edited:

Top