Important Melee, Hacks, and You -- New Hackers Start Here, in the OP!

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
Not sure if this has already been discovered but I thought I'd throw some notes down on SDI.
2 floating point numbers used for h_pos and y_pos respectively
44 = 42300000
12 = 41400000
Section A:
Format:
number1x number2y = number3 (number4)
number1 is the x_stick position
number2 is the y_stick position
number3 is the h_position_change / x_stick_change
number4 is number3 on the current row - number3 on the previous row
Think of number3's as a list with number4's being the difference of each value in the list
========
255x 128y = 0.061856
255x 129y = 0.061082 (0.000773) or (0.000774)
255x 130y = 0.061082
255x 131y = 0.061082
255x 132y = 0.061082
255x 133y = 0.061082
255x 134y = 0.061082
255x 140y = 0.061082
255x 150y = 0.060309 (0.000773)
150x 255y = 0.060309 (0.000773)
=== End of section A ===
150x 255y = (5.85)
(129x 255y) = (5.925000) // ROUNDED unlike H position
(255x 129y) = (5.924999)
5.925
Section B
Format:
(number1 , number2) = number3, number4

number1 = x_stick_value
number2 = y_stick_value
number3 = h_position_change
number4 = y_position_change
//(number4 is not not in parentheses if number3 isn't)
//number4 is left void if y_stick_value is 128
//symbol in between number1 and 2 doesn't matter, I was attempting to represent it as a function and scrapped it
=======
notepad : (192 - 128) = 4.799999 (
(193 - 128) = 4.875000 (0.075)
(194 - 128) = 4.950001
(195 - 128) = 5.025002
(195 + 195y) = (4.200001, 4.200001) 5.0250002 - 4.200001 = 0.825001
(195x + 199y) = (4.049999, 4.350000) (0.0604477, 0.630435)
(195x + 200y) = (4.049999, 4.350000) (0.0604477,)
(196x + 200y) = (4.050003, 4.350000)
(196x + 201y) = (4.049999, 4.350000)
(196 + 201y) = (4.0500003, 4.349998)
(196 + 201) = (4.049999, 4.350000) (probably this one)
(196, + 202) = (4.050003, 4.350000)
=== End of section B ===
SDI FORMULA
x_stick_change = x_stick_value - 128 (difference from neutral position)
y_stick_change = y_stick_value - 128 (difference from neutral position)
if (x > magic_deadzone) {
h_pos_y_deduction = (y_stick_change * 0.000773) //y_stick_change is rounded to some nearest unknown number frequently
h_pos = (0.07500 * x_stick_change) - (h_pos_y_deduction)
v_pos_x_deduction = (x_stick_change * 0.000773) //4 significant figures. rounded to nearest thousandth. Still has y_stick_change rounded to an unknown number frequently. More info on that at the bottom
y_pos = (0.07500 * y_stick_change) - (h_pos_y_deduction)
}

On rounding stick changes:
So sometimes the deduction value is not changed even when the respective stick position changes (see SECTION A tests)

the magic number 0.000773 was acquired by several tests at SECTION A with different y pos's with the same x pos and gathering the h pos change
the (h_pos divided by x_stick_change) can be represented as a table of values
Using the method of common differences you can
find the difference of each value and compare them to reveal it to be a linear equation
How I did it:
I looked at and set the (H/V player1 position values) to rounded numbers up to and during the frame I had player 2 hit me using frame advance and dolphin debug. I inputted various x and y stick positions and recorded the horizontal and vertical position changes with many times and recorded the results.
For any chance of this being a false pattern:
This was done on FD at
H-position: 44.0
V-position: 12.0
 
Last edited:

Achilles1515

Moderator
Moderator
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
Code:
*****************************
* Smash DI Formula Research *
*****************************
Function: 8008e4f0

-- Smash DI Requirements --

1)
If
(xjoy * xjoy) + (yjoy * yjoy) < (0.7 * 0.7)
Then apply no Smash DI.

2)
If cardinal direction change has not occurred in last 4 frames, then apply no Smash DI.

Else, apply Smash DI. 
--------

-- Applying Smash DI --

1) Set frames since last cardinal direction change for x & y axes to 254 frames.
    - Purpose of this is so that one fast joystick movement input cannot apply SDI multiple frames in a row, because requirement 2) from above will now fail. 
2) TopN-X movement change = xjoy * 6.0
3) TopN-Y movement change = yjoy * 6.0

---------

PlCo.dat offsets
0xa490   0.7 = minimum smash DI threshold formula number
0xa494    4 = cardinal direction change for Smash DI (greater than or equal to is false)
0xa498    6 = Smash DI x/y coord movement normalization (joystick value multiplied by this)
tatatat0 tatatat0 @schmooblidon @Gentlefox @Kadano
 
Last edited:

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
Code:
*****************************
* Smash DI Formula Research *
*****************************
Function: 8008e4f0

- Smash DI Prereqs -

1)
If
(xjoy * xjoy) + (yjoy * yjoy) < (0.7 * 0.7)
Then apply no Smash DI.

2)
If cardinal direction change has not occurred in last 4 frames, then apply no smash DI.

--------

- Applying Smash DI -

Set frames since last cardinal direction change for x & y to 254 frames.
TopN x change = xjoy * 6.0
TopN y change = yjoy * 6.0

---------

PlCo.dat offsets
0xa490   0.7 = minimum smash DI threshold formula number
0xa494    4 = cardinal direction change for Smash DI (greater than or equal to is false)
0xa498    6 = smash DI x/y coord movement normalization (joystick value multiplied by this)
tatatat0 tatatat0 @schmooblidon @Gentlefox @Kadano
Hmm, is there any reason why it seems that combining horizontal and vertical stick movement causes a weaker movement?
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
435
NNID
Psion312
r3 = character entity struct offset (I sometimes call this the external data offset)
I still refer to it as the Character Data pointer, since it's the function arguement and returned by the getSlotPointer function.

Any function that uses entity data just grabs the pointer from the generic entity struct before performing anything. I don't understand why to be honest, since every entity has the struct right before the rest of the data. There's so many redundant pointers in Melee that make no sense.
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
435
NNID
Psion312
Hey does anyone know exactly where shine mines occur and why?
This is a theory based on other character functions.

Shine is treated as some kind of shield (it sets the Shield angle to 1). A number of character moves, like C. Falcon/Dorf UpB, have physics checks for if Aerial State becomes Ground before the end of the routine, then throws a physics error.

Shields normally can't be used when you drop through a platform, which lead to an overlooked physics bug, where the projectile collision throws some kind of physics error and uses the last known "working" location.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
Hey, I want to verify the formula for Smash Charge in the Smash Charge format (E0XXYYYY ZZ000000) that Itaru gave me. Is it correct? Because I don't really get how to apply it for what I'm doing. Here are his notes:
That formula doesn't seem very right. If that was the formula I think there would be a MUCH steeper slope, and it would probably be a quadratic function or inverse variation. Anyways, the formula isn't very clear.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
I guess if you want a little more proof that that is the formula you could do a brute force search in PlCo.dat for 43800000 and see if any of them effect smash charging. I wonder what melee would do if you made it negative ( ͡° ͜ʖ ͡°).
 

Zeus_Da_master

Smash Journeyman
Joined
Jan 22, 2007
Messages
298
Location
Atlanta Ga
i'm stuck at step 2. in cmd i type in dspadpcm -d end00.dsp (the name of the dsp) and cmd says : DNS server not authoritative for zone
SSM Hacks





What to do:
0. Before you start
Extract the audio SSM files from the ISO with GC-Tool. The ones you might be concerned with are under \audio\us for English version sounds, while those under \audio but not under \us are Japanese version sounds. Put all these SSM files into a directory, categorize them, whatever. Heck, you can do one at a time, it doesn't matter. As long as you know what's what. Make sure you have the Wii SDK tools in the same directory, as well as ssmex.exe and your trusty command prompt.

1.Extract DSPs from the SSM
Make sure that the SSM you want to extract from is under the same folder as ssmex.exe and cmd.exe..now run cmd.exe and type in this
filename.ssm should be replaced with the SSM file that you're extracting from.
You should see a bunch of lines of data. Very useful data. The program will tell you how many DSPs there are, whether they are stereo or mono, and where they are located in the SSM. And it will extract them. (If you have Visual C++, the DSP files may have the VC++ Project icon. Don't double click when you edit them. Just right click and open with a hex editor.)

2. Convert to WAV
The SDK program dspadpcm.exe not only converts WAV->DSP, but also DSP->WAV. Nifty. So run cmd.exe and type in
NOTE: "-d" means "decode". The outputfile parameter is optional; the program by default creates a WAV with the same name as your DSP. Also, if you want it to create an AIFF instead of a WAV, type "-f" at the end of the line, as another parameter. If you want info on your DSP dumped in a TXT file, type "-c" as a parameter, too.



0. I extracted emblem.ssm from the \audio\us folder, and put it in a folder with ssmex.exe, cmd.exe, dspadpcm.exe, and soundfile.dll

1. I run cmd.exe, and I type
which outputs a bunch of DSPs for me, named "emblem00, emblem01, emblem02...etc"

2. I press enter to quit the program, and then I type
which outputs a WAV called emblem0b.wav. I listened to it in iTunes, and found it was the "hiii-ya" for Roy. I decided to edit it.
Opening Soundbooth with emblem0b.wav revealed it was 0.629 seconds in length, at 32kHz, 16 bit depth, mono, and had a max volume of "-1 db". OK..
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
Alright, so I want to make a character file bigger. I have added 0x200 zeros to captain falcon at 0x41C0, I have manually edited every single Goto(14xx) and subaction(1Cxx) commands. I changed the file size in the header represent the new file size and manually went through the pointers(I developed muscle memory for this so it only took about an hour. rip) for actions starting at 0x7CC4 incrementing 0x14 complying with the random break(It was somewhere in there. I remember.). It is still doing what it did even when I didn't do all this work. It just hangs on loading a stage. What else do I need to do?
 
Last edited:

flieskiller

Smash Journeyman
Joined
Jan 3, 2013
Messages
425
^ maybe when loading the character file in memory, it doesn't refer to the new size and it overwrites a file writen after. Does it freeze at the loading stage part when loading other characters and a stage after the Falcon file (so it's only the Falcon file the problem)?
 

Achilles1515

Moderator
Moderator
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
Alright, so I want to make a character file bigger. I have added 0x200 zeros to captain falcon at 0x41C0, I have manually edited every single Goto(14xx) and subaction(1Cxx) commands. I changed the file size in the header represent the new file size and manually went through the pointers(I developed muscle memory for this so it only took about an hour. rip) for actions starting at 0x7CC4 incrementing 0x14 complying with the random break(It was somewhere in there. I remember.). It is still doing what it did even when I didn't do all this work. It just hangs on loading a stage. What else do I need to do?
Did you simply try adding to the end of the file and then changing the header, without changing anything in between? I feel like I tried this a long time ago and it didn't work with character files.
 

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,010
Location
Sacramento, CA
Alright, so I want to make a character file bigger. I have added 0x200 zeros to captain falcon at 0x41C0, I have manually edited every single Goto(14xx) and subaction(1Cxx) commands. I changed the file size in the header represent the new file size and manually went through the pointers(I developed muscle memory for this so it only took about an hour. rip) for actions starting at 0x7CC4 incrementing 0x14 complying with the random break(It was somewhere in there. I remember.). It is still doing what it did even when I didn't do all this work. It just hangs on loading a stage. What else do I need to do?
You need to also update the pointer to the relocation/pointer table, which is right after the filesize at 0x4 (this value is also the exact size of the data block in the file). And for the table itself, you need to add 0x200 to each entry that points to or after 0x41C0, AND, for each entry, follow it to the pointer it points to in the file and add 0x200 to that if it points to or after 0x41C0. A script or program can do this in a matter of seconds rather than hours. So you can either make something using this, if you're going to want to do this a lot, or send the dat to me and I can add more space to it for you.

I don't know about the goto and subaction commands. Also I'm not sure what you mean by "went through the pointers for actions starting at 0x7CC4 incrementing 0x14 complying with the random break."

for sh*ts and giggles i tried this and replaced the png but nothing happened, ganon is still ganon, what did i go wrong?
Hard to know what you did wrong without knowing what you did. Need more info.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
You need to also update the pointer to the relocation/pointer table, which is right after the filesize at 0x4 (this value is also the exact size of the data block in the file). And for the table itself, you need to add 0x200 to each entry that points to or after 0x41C0, AND, for each entry, follow it to the pointer it points to in the file and add 0x200 to that if it points to or after 0x41C0. A script or program can do this in a matter of seconds rather than hours. So you can either make something using this, if you're going to want to do this a lot, or send the dat to me and I can add more space to it for you.

I don't know about the goto and subaction commands. Also I'm not sure what you mean by "went through the pointers for actions starting at 0x7CC4 incrementing 0x14 complying with the random break."


Hard to know what you did wrong without knowing what you did. Need more info.
I mean I found the distance between each pointer in the table, and just followed a pattern replacing pointers. I eventually reached a point where the pattern was offsetted for some weird reason. Oh, and I made sure to add space on the first pointer given, so I wouldn't accidentally replace a wrong pointer. I didn't actually try following the pointer because I just assumed they all pointed to subactions, but I guess I should have done that. I did update the pointer table location but forgot to include that. I probably did something wrong in all of that so I'll check out that link you gave me.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
I mean I found the distance between each pointer in the table, and just followed a pattern replacing pointers. I eventually reached a point where the pattern was offsetted for some weird reason. Oh, and I made sure to add space on the first pointer given, so I wouldn't accidentally replace a wrong pointer. I didn't actually try following the pointer because I just assumed they all pointed to subactions, but I guess I should have done that. I did update the pointer table location but forgot to include that. I probably did something wrong in all of that so I'll check out that link you gave me.
Can you explain to me its exact arguments? I can't really tell which part datData is supposed to be in relation to the other arguments. Is it the entire dat file as a string? Or is it what is not including the rtTable and the header.
 

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,010
Location
Sacramento, CA
i literally just exported this png, put in photoshop, thru the face on it, exported the png, replaced the png... effect: nothing happened
The texture you edited is for Ganon's off-screen model (the low-poly one that shows up in the magnifier bubble).

These are the textures you're looking for:

upload_2016-3-11_19-35-16.png


Can you explain to me its exact arguments? I can't really tell which part datData is supposed to be in relation to the other arguments. Is it the entire dat file as a string? Or is it what is not including the rtTable and the header.
Oh, yeah, I forgot to mention that, haha. Sorry. I could definitely make the function more-user friendly, but I just copy/pasted it from DTW real quick as an example for adding space. It has those global functions because files loaded into DTW are immediately broken into these parts to work with them a little easier.

For the arguments, "offset" is the offset in the file where your new space will begin, in bytes, not counting the file's header (so subtract 0x20), and "diff" is the amount of space to add, also in bytes. Both of these are integers. For the global variables, these are all hex strings; datDataHeader is just the header of the file (first 0x20 bytes); datData is everything after that, up until the relocation table (so the entire data block), and rtData is the relocation table (and doesn't include the nodes and string table that come after it). (Besides eyeballing it, you can find the end of the relocation/pointer table with: rtEnd = rtStart + (rtEntryCount * 4).)
 

Zeus_Da_master

Smash Journeyman
Joined
Jan 22, 2007
Messages
298
Location
Atlanta Ga
The texture you edited is for Ganon's off-screen model (the low-poly one that shows up in the magnifier bubble).
magnifier bubble?... but i was thinking maybe i needed to edit what you're saying... but what part of his face is the 431c0?

not always, but this is something i see sometimes, when i replace a png, it changes size. before it was 128x256 and when i replaced the original, for some reason it switched to say 32x64. why is that?

but thanks i got it to work, didn't even need to edit 431c0
 

Attachments

Last edited:

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,010
Location
Sacramento, CA
magnifier bubble?... but i was thinking maybe i needed to edit what you're saying... but what part of his face is the 431c0?

not always, but this is something i see sometimes, when i replace a png, it changes size. before it was 128x256 and when i replaced the original, for some reason it switched to say 32x64. why is that?

but thanks i got it to work, didn't even need to edit 431c0
Download the latest version of DTW; that's fixed in it. The GUI was updating to the size of the preview, rather than the true image.

Yeah, magnifier = the little circular window that pops up when your character goes offscreen.

I'm thinking 431c0 is his hair. If you want to try to find where a texture goes, you could always color it green or something that will stand out, and see what changes when you load up the game. Another useful technique is to add a grid to it, with various colored lines, so when you see it in-game, you can get a good idea of how the texture warps to wrap around the models, so you can plan/edit your textures accordingly.
 
Last edited:

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
The texture you edited is for Ganon's off-screen model (the low-poly one that shows up in the magnifier bubble).

These are the textures you're looking for:

View attachment 99901



Oh, yeah, I forgot to mention that, haha. Sorry. I could definitely make the function more-user friendly, but I just copy/pasted it from DTW real quick as an example for adding space. It has those global functions because files loaded into DTW are immediately broken into these parts to work with them a little easier.

For the arguments, "offset" is the offset in the file where your new space will begin, in bytes, not counting the file's header (so subtract 0x20), and "diff" is the amount of space to add, also in bytes. Both of these are integers. For the global variables, these are all hex strings; datDataHeader is just the header of the file (first 0x20 bytes); datData is everything after that, up until the relocation table (so the entire data block), and rtData is the relocation table (and doesn't include the nodes and string table that come after it). (Besides eyeballing it, you can find the end of the relocation/pointer table with: rtEnd = rtStart + (rtEntryCount * 4).)
Where can I find rtEntryCount? Also what is the function replaceHex()? Is it in a python library or a function you created?
 

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,010
Location
Sacramento, CA
Where can I find rtEntryCount? Also what is the function replaceHex()? Is it in a python library or a function you created?
rtEntryCount is the second 4 bytes in the file's header. replaceHex is just a simple function that replaces the hex at some given offset with some new hex. I forgot that was in there; but in this case, since the offset is 0 and the length of the new hex will be 16 (i.e. 8 bytes = 16 nibbles/hex characters), that function could be replaced and simplified to just ""{0:0{1}X}".format(newFilesize, 8) + "{0:0{1}X}".format(newRtStart, 8) + datDataHeader[16:]", which just replaces the two new values to the front of the file header. (The two .format() methods just take an int, and format it so that it's a hex string, padded with zeros up to 8 characters, i.e. 4 bytes.)

Although after writing this I looked at the function again and realized replaceHex() appears a few more times after where it's used for the header. So I'll just update that post with it included. My bad. Like I said, posting that was initially just meant to be a psuedocode example, not really a distributable script. You should be able to get it running now anyways though.

I'll also comment out the msg() function, since that's just something that was for myself.
 
Last edited:

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
rtEntryCount is the second 4 bytes in the file's header. replaceHex is just a simple function that replaces the hex at some given offset with some new hex. I forgot that was in there; but in this case, since the offset is 0 and the length of the new hex will be 16 (i.e. 8 bytes = 16 nibbles/hex characters), that function could be replaced and simplified to just ""{0:0{1}X}".format(newFilesize, 8) + "{0:0{1}X}".format(newRtStart, 8) + datDataHeader[16:]", which just replaces the two new values to the front of the file header. (The two .format() methods just take an int, and format it so that it's a hex string, padded with zeros up to 8 characters, i.e. 4 bytes.)

Although after writing this I looked at the function again and realized replaceHex() appears a few more times after where it's used for the header. So I'll just update that post with it included. My bad. Like I said, posting that was initially just meant to be a psuedocode example, not really a distributable script. You should be able to get it running now anyways though.

I'll also comment out the msg() function, since that's just something that was for myself.
Can you please also replace those replaceHex() functions in the code you originally posted? I really don't understand how to reimplement the workaround you posted 2 times because of a difference in variables used. The workaround just isn't readable enough for me to comprehend. Sorry about that. Also in the workaround you posted, where do the quotations start and end? Do I include the quotations surrounding the code or is it to show that there is code in the quotations?
Pretty much, is it
Code:
""{0:0{1}X}".format(newFilesize, 8) + "{0:0{1}X}".format(newRtStart, 8) + datDataHeader[16:]"
or
Code:
"{0:0{1}X}".format(newFilesize, 8) + "{0:0{1}X}".format(newRtStart, 8) + datDataHeader[16:]
Sorry about asking so much from you.
 

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,010
Location
Sacramento, CA
Can you please also replace those replaceHex() functions in the code you originally posted? I really don't understand how to reimplement the workaround you posted 2 times because of a difference in variables used. The workaround just isn't readable enough for me to comprehend. Sorry about that. Also in the workaround you posted, where do the quotations start and end? Do I include the quotations surrounding the code or is it to show that there is code in the quotations?
Pretty much, is it
Code:
""{0:0{1}X}".format(newFilesize, 8) + "{0:0{1}X}".format(newRtStart, 8) + datDataHeader[16:]"
or
Code:
"{0:0{1}X}".format(newFilesize, 8) + "{0:0{1}X}".format(newRtStart, 8) + datDataHeader[16:]
Sorry about asking so much from you.
The second. Though you don't need to worry about it, because I updated the post (the post in other thread with the function) with replaceHex() included.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
The second. Though you don't need to worry about it, because I updated the post (the post in other thread with the function) with replaceHex() included.
Found another undefined function. for nib in xrange(0, len(rtData), 8):. xrange isn't defined. Also by the way, just to be clear, the pointer the relocation table is at 0x4 and the amount of entries is at 0x8. so the end of the relocation table can be found with the value at 0x4 + (4 * value at 0x8). Edit: I think it was probably just a typo. Or at least I hope it was.
 
Last edited:

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,010
Location
Sacramento, CA
Found another undefined function. for nib in xrange(0, len(rtData), 8):. xrange isn't defined. Also by the way, just to be clear, the pointer the relocation table is at 0x4 and the amount of entries is at 0x8. so the end of the relocation table can be found with the value at 0x4 + (4 * value at 0x8). Edit: I think it was probably just a typo. Or at least I hope it was.
xrange is a function built into python 2.7. Which tells me you must be using python 3+. In that case, you can just replace it with range, which does the same thing as 2.7's xrange. (Even in 2.7, either should work. xrange is just more efficient in most cases.)

Oh, yeah, sorry, the table entry count is definitely at 08 and not 04. I was answering a lot of PMs and other things yesterday, so I must have got hasty, haha.
 
Last edited:

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
411
xrange is a function built into python 2.7. Which tells me you must be using python 3+. In that case, you can just replace it with range, which does the same thing as 2.7's xrange. (Even in 2.7, either should work. xrange is just more efficient in most cases.)

Oh, yeah, sorry, the table entry count is definitely at 08 and not 04. I was answering a lot of PMs and other things yesterday, so I must have got hasty, haha.
Alright, I am just having a lot of trouble with this. I've been trying stuff for a while now. I've been attempting to add 0x3C to 0x4a30 in PlSk.dat. First when I gathered the relocation table and the first 0x20 data isn't really pointers and/or the program didn't like it because they pointed outside the length of datData, so I had to include that as part of the datData. When I succesfully got the program to output the result as a textfile and i copied it over the datData and rtTable in the file and changed the fileSize and rtStart in the daDataHeader in the file it seemed to work ok. There were the zeros at 0x3C all fine. But when I loaded up crazyhand to view the subactions all of the subactions were around 0x900, and were just interpreting values that probably weren't subactions, which wasn't what I intended. [Here is my file]
 
Last edited:

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,010
Location
Sacramento, CA
Alright, I am just having a lot of trouble with this. I've been trying stuff for a while now. I've been attempting to add 0x3C to 0x4a30 in PlSk.dat. First when I gathered the relocation table and the first 0x20 data isn't really pointers and/or the program didn't like it because they pointed outside the length of datData, so I had to include that as part of the datData. When I succesfully got the program to output the result as a textfile and i copied it over the datData and rtTable in the file and changed the fileSize and rtStart in the daDataHeader in the file it seemed to work ok. There were the zeros at 0x3C all fine. But when I loaded up crazyhand to view the subactions all of the subactions were around 0x900, and were just interpreting values that probably weren't subactions, which wasn't what I intended. [Here is my file]
To get rtStart, you needed to add 0x20 to the pointer in the header. All pointers don't count the header so that they're relative to the start of the data block.

As I mentioned, this function won't touch the subactions or anything else that's not a pointer referenced by the pointer/relocation table (aside from moving them ahead in the file by 0x3C if they originally appeared at or after 0x4a30). It just adds more space to the structure at the specified place, and adjusts the other structures so that their pointers are correct, which is still necessary if you want more commands than there's space for. I don't know what you want to do with the subactions though.

Also, btw, instead of outputting to a text file and then copying over the data to another file using a hex editor, you could use the write method to open the new file in binary mode, and then write bytes to the file rather than hex. To do this, instead of using "w+" for the second argument to write, use "w+b". And then when you write the data to it, use "datfile.write( bytearray.fromhex(datData) )". bytearray.fromhex() encodes the data as a byte array. I noticed you don't have the new header being output to the new file, which you could do at the same time, e.g. "datfile.write( bytearray.fromhex(datDataHeader+datData) )".
 

adjective

Smash Rookie
Joined
Nov 4, 2015
Messages
12
Location
Toronto, Ontario
No idea what the current understanding of melee's skeleton format is. Most of the posts I cant find are a few years old. I spent some time trying to write a bvh exporter and I've been fiddling with different interpretations of the export flags, giving me this:



These models are Roy, Shiek, Fox, and Fox with a different interpretation of the export flags.

I'm also trying to figure out the figatree internals. I think I've got an idea of how the figatree (PL**AJ.dat) files are structured
(consecutive HAL datfiles concatenated with offsets corresponding to values given in the player subaction headers). These datfiles
have a single file at the end of their data section, structured like this


Code:
figatree_header {
    uint32_t unknown = 1
    uint32_t unknown = 0
    float unknown = usually the number of frames as a float + 1, but 200 for some wait animations
    uint32_t probablyAnOffset  = an integer in 0xXXXX range
{
These are some more comprehensive (if a little unintelligible) thoughts on figatrees

I've tried pointing this probablyAnOffset value from the origin of the mmapped file (the root of the Pl**AJ.dat file) without much luck, as the following region isn't large enough to contain meaningful animation data, doesn't look alike a group of offsets, and I'm not sure what else it could be. This is what the beginning of the region pointed to by Bowser's AirThrowLw animation looks like.



It doesn't look like an array of floats, since the magnitude of the values is so low, and the int interpretations are all too high to be offsets.

if the offset is within the same hal file (which would make more sense), then the region looks like this, BUT is nowhere near large enough to contain actual animation data, and once more, does not look like offsets to more animation data.



This is promising because it looks like it's null terminated, but I'm not sure where to go from here
EDIT: 19 is the maximum length for this block, since expanding it further steps onto the offset table of the internal HAL datfile.
 
Last edited:

D3WD

Smash Rookie
Joined
Jan 12, 2012
Messages
8
Hey - I have been wondering about this as well. @Tcll and @revel8n discussed some of the file formatting in depth (rev goes deeper into how the actual data structure works). Other than Universal Model Converter you are posting the most concrete thing about actual bones from the Pl**AJ.dat files.
 

D3WD

Smash Rookie
Joined
Jan 12, 2012
Messages
8
update on my previous post in this thread: fixed the arms of the characters by taking another look at the flags. Feels good :dkmelee:.

Everything seems mostly sane (weird bones for pichu's ears, jigg's tuft, donkey kong's tie, etc are all in the expected places)

Legs and feet are still pretty odd though.

Hey Can we create a new thread out of this - it's buried pretty deep here in this thread and I want to work on it and watch community progress being made in this area. @Tcll 's UMC is the only other thing I have seen on smashboards.
 

Achilles1515

Moderator
Moderator
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
I still refer to it as the Character Data pointer, since it's the function arguement and returned by the getSlotPointer function.

Any function that uses entity data just grabs the pointer from the generic entity struct before performing anything. I don't understand why to be honest, since every entity has the struct right before the rest of the data. There's so many redundant pointers in Melee that make no sense.
Just wanted to chime in that the entity data is not always immediately after the entity structure. This is normally the case for entitys not spawned at the beginning of the match, like items and characters (multi-man matches for example). I just fixed a bug in the newest 20XX where Crazy Hand in Classic Mode was not dying properly. I was loading the internal character ID from 0x64(r3), when I should have been doing it the way the game does; lwz r4,0x2c(r3) and then lwz r4,0x4(r4). Crazy Hand's data was not immediately after his struct because he gets spawned mid-match.
 
Last edited:
Top