Hey, we get it. However this website is run by and for the community... and it needs ads in order to keep running.
Please disable your adblock on Smashboards, or go premium to hide all advertisements and this notice.Alternatively, this ad may have just failed to load. Woops!

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

Smash Journeyman

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.

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.

Smash Cadet

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:

Smash Journeyman

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.

Smash Journeyman

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 ( ͡° ͜ʖ ͡°).

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 inNOTE: "-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..

Smash Journeyman

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?

Smash Journeyman

^ 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)?

Moderator

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?

Attachments

Technowizard

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."

Smash Journeyman

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.

Smash Journeyman

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.

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).)

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.

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).)

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.

Smash Journeyman

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

Technowizard

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

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.

Technowizard

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.

Smash Journeyman

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]

Technowizard

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) )".

Smash Rookie

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

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.

Smash Rookie

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.

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.

Moderator

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.