• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

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

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
474
NNID
Psion312
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.
Yeah, my other point was about how Article FP and some other things have redundant pointers. I understood why the Entity struct did that, at least in the context of items and whatnot.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
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) )".
Alright, I finally figured out what was wrong with the code you gave me.
Code:
# If the pointer appears after the change, update its address in the relocation table accordingly.
if rtEntryValue >= offset:
newRtEntryValue = rtEntryValue + diff
datData = replaceHex( datData, rtEntryAddress, "{0:0{1}X}".format(newRtEntryValue, 8) )
entriesUpdated += 1
When it checks if rtEntryValue >= offset, it adds the changed rtEntryvalue on to the datData, but if rtEntryValue < offset
it does nothing, and excludes it from datData, acting as if it never existed.
So I fixed that and the fixed code is
Code:
def extendDataSpace( offset, diff):
    """ This function will expand the data area at the given offset, starting at the first argument. The second argument is the amount to increase by.
        All pointers occurring after the sum of the two arguments will be recalculated. """

    def replaceHex(hexData, offset, newHex): # Input takes a string, int, and string, respectively.
            offset = offset * 2 # Doubled to count by nibbles rather than bytes, since the data is just a string.
            codeEndPoint = offset + len(newHex)
            """
            print(type(hexData))
            print (offset)
            print(codeEndPoint)
            """
            return hexData[:int(offset)] + newHex + hexData[int(codeEndPoint):]
    """
    def deHex(hex_num):
      numerals = []
      for i in hex_num:
        numerals.append(i)
      numerals.reverse()
      new_values = []
      for i in range(0,len(numerals)):
         try:
           new_values.append(numerals[i] * (16 ** i))
         except ValueError:
           num_val = numerals[i]
           if num_val == "A":
             new_values.append(10  * (16 ** i))
           elif num_val == "B":
             new_values.append(11  * (16 ** i))
           elif num_val == "C":
             new_values.append(12  * (16 ** i))
           elif num_val == "D":
             new_values.append(13  * (16 ** i))
           elif num_val == "E":
             new_values.append(14  * (16 ** i))
           elif num_val == "F":
             new_values.append(15  * (16 ** i))
      new_number = 0
      numerals=[]
      for i in new_values:
        new_number + i
      return new_number
    """


    global datDataHeader, datData, rtData, after
    if datDataHeader != '' and datData != '' and rtData != '' and after !='':
        #After is the data right after the rtData
        # Update the file header with the new file size and start of the relocation table.
        filesize = int(datDataHeader[:8], 16)
        newFilesize = filesize + diff
        rtStart = int(datDataHeader[8:16], 16) # Size of the data block
        newRtStart = rtStart + diff
        datDataHeader = replaceHex(datDataHeader, 0, "{0:0{1}X}".format(newFilesize, 8) + "{0:0{1}X}".format(newRtStart, 8))

        # For each entry in the relocation table, update the address it points to, and the value of the pointer there, if they point to locations beyond the extended space.
        entriesUpdated = 0
        pointersUpdated = 0
        for nib in range(0, len(rtData), 8):
            rtEntryNum = (nib/8)
            rtEntryAddress = rtStart + (rtEntryNum * 4)
            rtEntryString = rtData[nib:nib+8]
            rtEntryValue = int(rtEntryString, 16) # i.e. the pointer address
            """
            if nib >= 200:
              print ("rtEntryString: ", rtEntryString)
              print ("rtEntryValue: ", rtEntryValue)
              input("S")
              exit()
            """
            pointerString = datData[rtEntryValue * 2:(rtEntryValue + 4) * 2] # Multipled by 2 because this is per character/nibble, not per byte.
            """
            print ("rtStart: ", rtStart)
            print ("Num: ", rtEntryNum)
            print ("String: ", rtEntryString)
            print ("Address: ", rtEntryAddress)
            print ("Start: " , rtEntryValue*2)
            print("End: ", (rtEntryValue+4)*2)
            print ("Len: ", len(datData))
            print ("Pointer string: ", pointerString)
            print ("Len of pointer string: " + str(len(pointerString)))
            print (type(pointerString))
            """
            pointerValue = int(pointerString, 16)

            # If the pointer appears after the change, update its address in the relocation table accordingly.
            if rtEntryValue >= offset:
                newRtEntryValue = rtEntryValue + diff
                datData = replaceHex(datData, rtEntryAddress, "{0:0{1}X}".format(newRtEntryValue, 8))
                #print ("rtEntryAddress: " + str(rtEntryAddress))
                #print ("Old data: ", rtEntryValue)
                #print ("New Data: ", "{0:0{1}X}".format(newRtEntryValue, 8))
                #input("S")
                #exit()
                entriesUpdated += 1
            else: #doesn't just ignore unused stuff
                datData = replaceHex(datData, rtEntryAddress, "{0:0{1}X}".format(rtEntryValue, 8))

            # If the place that the pointer points to is after the space change, update its value accordingly.
            if pointerValue >= offset:
                newPointerValue = pointerValue + diff
                datData = replaceHex(datData, rtEntryValue, "{0:0{1}X}".format(newPointerValue, 8))
                pointersUpdated += 1

        # Fill the newly extended space with zeros. (Values doubled to count by nibbles rather than bytes, since the data is just a string.)
        datData = datData[0:offset * 2] + '0'.zfill(diff*2) + datData[offset * 2:]
        datfile = open(str(random.randrange(0,10)) + str(random.randrange(0,10)) +   str(random.randrange(0,10)) +   str(random.randrange(0,10)) +   str(random.randrange(0,10)) +  ".txt", "w+")
        datfile.write(datDataHeader + datData + after)
        datfile.close()
Anyways, even with this fixed code it still hangs on starting a stage. The filesize is correct now though.
Edit: This is what I meant by it reads subactions as random garble.
 
Last edited:

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
Is there any way to translate the units of hitbox size into direct x/y size used for player positions?
 

revel8n

Smash Cadet
Joined
Dec 1, 2009
Messages
51
Any idea why it is that number? I mean there has to be something special about that particular number. Hmmm. Well still, thanks for the info!
When in doubt, take number and do this: 1.0 / number

0.003906 = 1.0 / 0.003906 = 256.01638504864311315924219150026
with full precision it would probably be 1 / 256 = 0.00390625

Divisions by powers of 2 can be common for packing floating point data into smaller integer storage space.
 
Last edited:

DRGN

Technowizard
Moderator
Joined
Aug 20, 2005
Messages
2,179
Location
Sacramento, CA
Do my eyes deceive me...?


The renowned and rare revel reappears! (And ripe with reciprocal revelations.)
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
Do my eyes deceive me...?


The renowned and rare revel reappears! (And ripe with reciprocal revelations.)
Hey, pay up on that script mate. Its still not working. Did you leave something out of it that seemed to be out of context or did the script even work in the first place.
 

DRGN

Technowizard
Moderator
Joined
Aug 20, 2005
Messages
2,179
Location
Sacramento, CA
Hey, pay up on that script mate. Its still not working. Did you leave something out of it that seemed to be out of context or did the script even work in the first place.
It definitely works on my end, since I've used it to create several working files (which I've also shared as part of various hacks, and no one mentioned that the files didn't work). There are a number of things you're doing differently than my implementation. And I've never done anything with subactions, meaning A) I don't know about those, and B) the function isn't going to touch them (unless there's anything in the rtTable pointing to something within them). As I said in the beginning though, if you'd like, you can send the file to me and tell me what area you'd like to extend and I can do it. Or if you still want to get your script working, PM me and I'll help you work on it.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
Introduction:
Alright, so I kinda was interested in the similarities between melee's file and other game's files in an effort to try to further the understanding of melee's files and I found some astonishing similarities in games. I decided to look at Fire Emblem Path of Radiance's (hereafter referred to as PoR) to files and I started off looking at Face/FE8anim.bin. Now remember, this is a completely different file type made by a completely different company. Or is it really made by a different company? More on that later ;).
Similarities:
Anyways within 5 minutes of opening up the FE8anim.bin I noticed some striking similarities to .dat files. I'm going to list them in spoilers.
String Table:
If you have gone through any .dat files you will have seen this before, its always there somewhere.
I'm going to show side-by-side comparision of a .dat string table and a PoR's string table.

Now there isn't really much to say about this. Both of them use their own arbitrary notation and structure with melee using figatree and PoR using its own structure that I have not spent enough time to figure out. However, it is very obvious to me that both of them perform very similar functions and simply list off strings. That is all there really is to say about those.
Header:
Now this is something very interesting, its at the top of every .dat file and is exactly 0x20 bytes in length, using the following format.
0x0: Filesize
0x4: Pointer to relocation table
0x8: Relocation table entries
0xC: int 1 or "00000001"
0x10: int 0 or "00000000"
with the rest being unknown or useless to me
Now I am going to show side by side comparisons of Melee's .dat file headers and PoR's headers

Now lets take a look at both of these.
Here is some info for both of the files and then compare them to the header's information.
Code:
             Filesize:              Relocation Table Address:             End of  Relocation Table:             Relocation Table Entries:
Melee:       0x3F70A                0x3BD00                               0x3F6D8                               0xE7E
PoR:         0x5C49                 0x4C58                                0x5C38                                0x3F8
Now if I look at the first double word of both of the headers they both match the filesize of the respective file.
For where the relocation table they both match up, being 0x20 bytes behind the actual table because the header is ignored in pointers(that is yet another similarity)
Now for how to calculate the end of the relocation table
I've learned from DRGN that to calculate the end of the relocation table you take the start of the relocation table + (the number of entries * 4)
Now to try this with both of the files
Melee:
0x3BD00 + (0xE7E * 4)
0x3BD00 + (0x39F8)
-------------------------------
0x3F6D8
==================
PoR:
0x4C58 + (0x3F8 * 4)
0x4C58 + (0xFE0)
-------------------------------
0x5C38​
The formula matches with both of the files, proving that they use similar formats.
Relocation Table:
Even though I already proved the similarities in the relocation table in the section on the header I still think it would be useful to see a side-by-side comparison of the two files.

It is very easy to notice the similarities in the two tables. Both of them start with the Entry "00000004". As I've already said a lot about the tables in the header section, that is all I have to say.
Conclusion:
Now I have heard before that .dat files are a proprietary or otherwise unique format created by HAL laboratory, but I think this proves otherwise. Since HAL Laboratory did not have a hand in PoR how can it be that the structure can be so similar? After doing some research I found that one of the companies who had a part in the development of melee, Intelligent Systems, is one of the main developers of PoR. Does this mean that Intelligent Systems created this format or is it a common format throughout many games? That is a question that would require more research.
As for the time of usage of the format the release dates of the two games are 4 years apart, with melee in 2001 and PoR in 2005. This means again either that this is a common format or that Intelligent Systems decided to recycle a format after 4 years. Now if there is a 4 year time frame in-between the two games there must be some differences right? What I infer is that within those 4 years there were likely to have been some improvements to the file structure of this format that can be reapplied to Melee. Maybe as modders we can learn from the improvements in readability or structure of this later game to better understand or improve the structure of Melee. Well that is all I have to say about this for now. It was a really interesting topic to me, and I have no idea where I should be putting this post. Congratulations if you actually got through this giant mess of a post.
 
Last edited:

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
Awesome video! The kill at 1:15 was my favorite. Did you make this the SDR male wireframe toggle?
It seems more like he physically swapped the characters being played in whatever wireframe mode he is playing. I think this because of the sound effects of the "wireframes", the different stock icons, and the fact that the wireframes can use special moves while he seems to not be able to.
 

revel8n

Smash Cadet
Joined
Dec 1, 2009
Messages
51
Now I have heard before that .dat files are a proprietary or otherwise unique format created by HAL laboratory, but I think this proves otherwise.
The dat file format is not exclusive to HAL. HAL was involved in the creation of a library called sysdolphin which was used by numerous developers on nintendo platforms as a starting point for development on the system at the time. So there can be seen a number of games that have similar formats. Sonic Unleashed and Pokemon Colosseum use modified versions of the formats, and i am sure there are many others that originally started with them. Melee just happens to also use the library. You can find references to sysdolphin within the binary.
 
Last edited:

MassProducedWaffles

Smash Cadet
Joined
Apr 29, 2014
Messages
25
Location
Sandy, Utah
Hey everyone! Me and a buddy have been really interested in neural networks lately so we want to try and make a neural network that learns to play Melee. We're CS majors so we know a decent amount. We are trying to extract data from melee to use to train the neural network. Some examples of data we want would be to feed to the neural network would be the percentage of each player and their position and current state. We have all the Dolphin source code running and debugging at the moment. We'd like to edit the source code to log the data we need to a file. Ideally this file would have a log of data for every frame during a game: percentages, positions, ect. Does anyone have any experience with the Dolphin source code that would know the best way to implement this? Or if you have any better ideas to how to do this that would be great too.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
Hey everyone! Me and a buddy have been really interested in neural networks lately so we want to try and make a neural network that learns to play Melee. We're CS majors so we know a decent amount. We are trying to extract data from melee to use to train the neural network. Some examples of data we want would be to feed to the neural network would be the percentage of each player and their position and current state. We have all the Dolphin source code running and debugging at the moment. We'd like to edit the source code to log the data we need to a file. Ideally this file would have a log of data for every frame during a game: percentages, positions, ect. Does anyone have any experience with the Dolphin source code that would know the best way to implement this? Or if you have any better ideas to how to do this that would be great too.
This sounds really interesting and I could give you some more info on it but I bet someone like Achilles1515 Achilles1515 or @Dan Salvato would love working on it with you directly, since they have more experience on the ASM side of this. Anyways, if you want to check some stuff out yourself you can look at https://docs.google.com/spreadsheets/d/1JX2w-r2fuvWuNgGb6D3Cs4wHQKLFegZe2jhbBuIhCG8 . Hopefully you guys can make a youtube video of something of this when you are done, because this sounds like an amazing idea that I actually think has been talked about before but never done. Actually maybe I can give you a hint on the basis of how you could gather this data. You'd want to start by every frame iterating through the character's datas at (
0x80453130,
0x80453FC0,
0x80454E50,
0x80455CE0
) respectively.
Percent can be gathered at 0x60 from the address pointed to, stocks left at 0x8E, Suicides at 0x8C. Some other useful stuff might be the total player attack count at 0xE8,
Total Connected Attacks at 0xF0,
Total Damage Received at 0xD1C, and Total Damage Given at 0xD28)
Now after you gather whatever you want from there you're going to want to go to the address pointed to at 0xB0. in there at 0xB0 and 0xB4 you can find the horizontal and vertical position of the player respectively. I'm assuming thats the sort of data you would need.
 
Last edited:

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
474
NNID
Psion312
Hey everyone! Me and a buddy have been really interested in neural networks lately so we want to try and make a neural network that learns to play Melee. We're CS majors so we know a decent amount. We are trying to extract data from melee to use to train the neural network. Some examples of data we want would be to feed to the neural network would be the percentage of each player and their position and current state. We have all the Dolphin source code running and debugging at the moment. We'd like to edit the source code to log the data we need to a file. Ideally this file would have a log of data for every frame during a game: percentages, positions, ect. Does anyone have any experience with the Dolphin source code that would know the best way to implement this? Or if you have any better ideas to how to do this that would be great too.
Source/Core/Core/GeckoCode.cpp uses every method you'd need to do it on Dolphin through Windows or Linux.

If you want to do it outside of Dolphin, look into Dolphin's memory watcher used by other bots.
 

MassProducedWaffles

Smash Cadet
Joined
Apr 29, 2014
Messages
25
Location
Sandy, Utah
Source/Core/Core/GeckoCode.cpp uses every method you'd need to do it on Dolphin through Windows or Linux.

If you want to do it outside of Dolphin, look into Dolphin's memory watcher used by other bots.
This sounds really interesting and I could give you some more info on it but I bet someone like Achilles1515 Achilles1515 or @Dan Salvato would love working on it with you directly, since they have more experience on the ASM side of this. Anyways, if you want to check some stuff out yourself you can look at https://docs.google.com/spreadsheets/d/1JX2w-r2fuvWuNgGb6D3Cs4wHQKLFegZe2jhbBuIhCG8 . Hopefully you guys can make a youtube video of something of this when you are done, because this sounds like an amazing idea that I actually think has been talked about before but never done. Actually maybe I can give you a hint on the basis of how you could gather this data. You'd want to start by every frame iterating through the character's datas at (
0x80453130,
0x80453FC0,
0x80454E50,
0x80455CE0
) respectively.
Percent can be gathered at 0x60 from the address pointed to, stocks left at 0x8E, Suicides at 0x8C. Some other useful stuff might be the total player attack count at 0xE8,
Total Connected Attacks at 0xF0,
Total Damage Received at 0xD1C, and Total Damage Given at 0xD28)
Now after you gather whatever you want from there you're going to want to go to the address pointed to at 0xB0. in there at 0xB0 and 0xB4 you can find the horizontal and vertical position of the player respectively. I'm assuming thats the sort of data you would need.
Thanks for the info guys! I've seen that table before tatatat0 and it's extremely useful. Seems like I'll be able to get all the character data I need from it. I might have slightly mislead you though. I don't really need help with any of the Melee ASM code. I've probably done more ASM coding than anything else, and have made some Gecko codes and small mods for melee in the past for fun. Also, we aren't planning on doing any modifications to the melee code, at least not for now. We just need to read some of the character data memory addresses every frame and log them.

What I am struggling with is editing Dolphin to do this. The Dolphin source code is slightly big and overwhelming so I'm not exactly sure where to look. So far my search has led me Memmap.cpp where I am looking at the Read functions. They seem to return the value at the GC memory address passed to them, which I think is exactly what I want. However, it says that GC RAM exists from 0x00000000 to 0x02000000 but the memory addresses in the Melee spreadsheet are all around 0x80xxxxxx. Now, before I embarrass myself, I'm almost positive I ran into this exact problem when I was doing work with Melee ASM, but it has been a long time and I don't remember what I ended up figuring out.

BTW, our goal with this project is to have a neural network learn how you play and inherit your play style, which neural networks are extremely good at. If it is successful, a pro could use our project and let a neural network learn their play style. This neural network could be distributed so that anyone could "practice against the pro". That's the dream anyways :D

Again, thanks for the help guys!
 

revel8n

Smash Cadet
Joined
Dec 1, 2009
Messages
51
What I am struggling with is editing Dolphin to do this. The Dolphin source code is slightly big and overwhelming so I'm not exactly sure where to look. So far my search has led me Memmap.cpp where I am looking at the Read functions. They seem to return the value at the GC memory address passed to them, which I think is exactly what I want. However, it says that GC RAM exists from 0x00000000 to 0x02000000 but the memory addresses in the Melee spreadsheet are all around 0x80xxxxxx. Now, before I embarrass myself, I'm almost positive I ran into this exact problem when I was doing work with Melee ASM, but it has been a long time and I don't remember what I ended up figuring out.
http://www.gc-forever.com/yagcd/chap4.html#sec4
http://wiibrew.org/wiki/Memory_Map

Addresses that start with 0x80......, etc. are simply "special" (do not take that as a technical term, heh) interpretations of memory mapped to the underlying physical address range. In this case stating that access using those address ranges are cached. Addresses that start with 0xC0...... are technically the same memory range as those that start with 0x80...... but are not cached.

Sounds like an interesting project, would definitely be interesting in the results obtained should you make some progress.
 
Last edited:

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
Thanks for the info guys! I've seen that table before tatatat0 and it's extremely useful. Seems like I'll be able to get all the character data I need from it. I might have slightly mislead you though. I don't really need help with any of the Melee ASM code. I've probably done more ASM coding than anything else, and have made some Gecko codes and small mods for melee in the past for fun. Also, we aren't planning on doing any modifications to the melee code, at least not for now. We just need to read some of the character data memory addresses every frame and log them.

What I am struggling with is editing Dolphin to do this. The Dolphin source code is slightly big and overwhelming so I'm not exactly sure where to look. So far my search has led me Memmap.cpp where I am looking at the Read functions. They seem to return the value at the GC memory address passed to them, which I think is exactly what I want. However, it says that GC RAM exists from 0x00000000 to 0x02000000 but the memory addresses in the Melee spreadsheet are all around 0x80xxxxxx. Now, before I embarrass myself, I'm almost positive I ran into this exact problem when I was doing work with Melee ASM, but it has been a long time and I don't remember what I ended up figuring out.

BTW, our goal with this project is to have a neural network learn how you play and inherit your play style, which neural networks are extremely good at. If it is successful, a pro could use our project and let a neural network learn their play style. This neural network could be distributed so that anyone could "practice against the pro". That's the dream anyways :D

Again, thanks for the help guys!
I'm not sure if what you are doing is similar to Playfun and MarI/O, which are two examples of neural networks that I have seen, but there is a lot of things you could base fitness or "What is good" for the AI to potentially learn. I don't really know what it would be called because I haven't done indepth research into this topic really but I think you can understand. If you do get that input working there are a lot of other things that could be factors or w/e you want to call them for "what is good" or things for the bot to potentially watch like doing different things during action states(Jumping, running, etc..), stale moves (such as having more of the same move in the stale move index lowering fitness or something), knockback angle being launched from (at 0x18A8 from character data), hitlag currently being suffered at (0x19BC), shield size at (0x19F8), and maybe some other stuff. I don't really know what you are planning to do or how much data you plan on letting the AI use but there is a lot of possibilities for data to be read in various ways. Like it could learn DI patterns, SDI, Not shielding at low shield size, or being a dumbass and getting its shield broken. Anyways, thats all I have for input on the subject probably, as I have no clue how such a AI would be formatted or structured. Seems pretty neat though.
 

SinsOfApathy

Smash Journeyman
Joined
Feb 24, 2015
Messages
474
NNID
Psion312
I'm not sure if what you are doing is similar to Playfun and MarI/O
Those are NN are running on deterministic games. Most NN aren't very good with non-determinism, which any game involving another player is (unless it's only fighting Melee's bots). That's why for the most part, I think it's a square peg in a circular hole issue, as a I said to the last few people talking about NNs.

https://arxiv.org/ftp/arxiv/papers/1507/1507.04029.pdf shows a comparison of a selection existing NN on Pong, which obviously has less features overall.

Dantarion's Street Fighter system is by far the best approach with a reaction-based event system that runs from a script. Level11CPU and the other Melee AI are close to that, but they're definitely lacking on obvious features.
 
Last edited:

DRGN

Technowizard
Moderator
Joined
Aug 20, 2005
Messages
2,179
Location
Sacramento, CA
What do we know about MnSlChr's file structure?

I know @zankyou was able to modify the angle/positions of the selection icons, but I'm doubting that that was done using the Texture Structures (though I haven't found the time to test that yet).

And I know Achilles1515 Achilles1515 found data on the selection regions (including position data), but that was in RAM only.

Specifically, I'd like to know more about the structures. (i.e. does it have object/material structures? what else is above those if they're there?) I'm starting to look into it myself, but I thought I'd first ask if there's already any info documented on it.
 

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
What do we know about MnSlChr's file structure?

I know @zankyou was able to modify the angle/positions of the selection icons, but I'm doubting that that was done using the Texture Structures (though I haven't found the time to test that yet).

And I know Achilles1515 Achilles1515 found data on the selection regions (including position data), but that was in RAM only.

Specifically, I'd like to know more about the structures. (i.e. does it have object/material structures? what else is above those if they're there?) I'm starting to look into it myself, but I thought I'd first ask if there's already any info documented on it.
Regarding modifying the angle/positions of char select icons, Im fairly certain each one is a bone struct. So yeah, just keep backtracking from the texture struct.

But idk about overall root structure.
 

tatatat0

Smash Journeyman
Joined
Jan 28, 2015
Messages
412
Regarding modifying the angle/positions of char select icons, Im fairly certain each one is a bone struct. So yeah, just keep backtracking from the texture struct.

But idk about overall root structure.
I wrote some notes on it, check the here.
 

DRGN

Technowizard
Moderator
Joined
Aug 20, 2005
Messages
2,179
Location
Sacramento, CA
Some notes on ISO rebuilding. Might get lost, so bookmark it if you ever plan to do any coding for ISO rebuilding (I feel like we should have a thread for full documentation on this). There are certainly other potential programs that could benefit from it.


I found out that offsets for file starts must be aligned to (i.e. be a multiple of) 4 bytes. I rebuilt some ISOs that I believe had all correct calculations for the FST, but when they had files with offsets of 0x_____3 or 0x_____a for example, they wouldn't boot. After this I at first thought the alignment was probably to 16 bytes, or maybe 32, but I noticed that even the vanilla game has some offsets starting at 0x__c, etc.

Also, I've done some testing, and I think that when the game loads a file, probably as an extra step for validation, it must be comparing the filesize given in the FST with the filesize given in the file's header. Because apparently if they're not the same, the game freezes.

I added some extra padding after a stage file, updating the FST (including giving it the filesize of the stage file counting the new padding) and preserving the 4 byte alignment, but not updating the file's header to include the padding) and the game would boot and run, but then would freeze when trying to load that file. If I then updated the file header to include that extra padding as part of the file, it would work. I tried doing this with several different byte differences/padding lengths.

At first I figured it wouldn't matter if the filesizes were different; I figured it'd be fine regardless of which value was used to transfer the file to RAM, as long as they both included at least the one empty byte at the file's end. Just FYI. Since it's probably good practice to keep them the same anyway. I think it's best to just exclude the padding (if required to preserve alignment) from both so that the new file doesn't have to be modified.
 
Last edited:

DRGN

Technowizard
Moderator
Joined
Aug 20, 2005
Messages
2,179
Location
Sacramento, CA
I actually don't think it's that unrealistic. There are a few things that might be tricky to figure out (namely, making things move dynamically, such as having the selection arrow move back and forth), but for the most part I think this could be done now.

Quite tedious, but still possible.
 

Acryte

Smash Ace
Joined
Mar 30, 2005
Messages
986
Plenty of people in the community wouldn't mind throwing bounties or cash at such work.
 
Top Bottom