Quote from: shanus;9619461Fighter.pac injections follow a simple protocol:
STRATEGY
Say we have an action in fighter.pac, such as taunts. Say we want to make a code for taunt canceling a la 64 where you can cancel the taunt by entering the "teeter" animation at the edge. What I want to do is the following:
-Overwrite a safe location inside of taunt action in fighter.pac with a Go to line.
-This Go to line points to a data parameter in my code whose offset points to the start of my PSA commands to inject.
-At the end of my PSA commands, I write another Go to line which points back to fighter.pac to return to the next command after what I wrote over (or commands later in the same action)
Now for the structure of fighter.pac injections:
HEADER
DATA
COMMANDS
FOOTER
The header describes where in memory you overwrite.
The data section is what the PSA commands refer to in memory.
The commands section is a sequential list, in order, which refer to the data section (IF THEY HAVE parameters).
The footer section is where you overwrite in fighter.pac with a go to line.
SECTION 1. Commands
1. In PSA, write out the code you wish to inject for ALL characters. You need to make sure this code is finalized, as writing these codes requires significant structure control and rewriting it can be a pain and time consuming.
So for taunt canceling, I want to do the following simple code.
Change Action: 7C, req=3A
Or in command language:
02010200 XXXXXXXX where XXXXXXXX will be the data section we point to in memory.
Note the number of parameters this code calls for, 2. If this number is 0, replace the X's with ALL ZEROES.
SECTION 2. DATA
Writing the data is very simple. As I described before, i wanted to write:Code SelectChange Action: 7C, req=3A
So we call the change action, but need the data to tell it 7C, req 3A.
The data format for each parameter is as follows:Code Select0000000V DATADATA
V is the format the data takes.
0 - Value
1- Scalar
2- Pointer
3- Boolean
4 - ???
5- Variable
6- Requirement
DATADATA is the actual data you wish to write.
So for our code:Code SelectChange Action: 7C, req=3A
The data would be:Code Select
00000000 0000007C
00000006 0000003A
But, let us not forget that we also need to have data for the two "Go to" statements this code uses.
So, we neeed two data sets which are pointers such as:Code Select
00000002 YYYYYYYY
00000002 ZZZZZZZZ
That brings our total data section up to:Code Select
00000000 0000007C
00000006 0000003A
00000002 YYYYYYYY
00000002 ZZZZZZZZ
So now we need to begin constructing the code.
We have the following:Code Select
---DATA---
00000000 0000007C
00000006 0000003A
00000002 YYYYYYYY
00000002 ZZZZZZZZ
---Commands---
02010200 XXXXXXXX
To keep progressing, we need to choose an area in memory to write to, and also figure out our injection point.
SECTION 3. FOOTER
Within fighter.pac, viewable through OpenSA2 [download: ]http://opensa.dantarion.com/wiki/Main_Page]
Step 1: Find the action of interest for your code. A very rough (some of these are wrong) list of action IDs are located here: http://www.smashboards.com/showthread.php?t=239768
Step 2: Find a safe injection point for your code. What happens is that a line in fighter.pac must be replaced with a Go To line. As such, when you are choosing your area to inject, you don't want to overwrite an Else statement and break the flow of l]ogic. It's best to overwrite something simple, especially when you are learning.
Step 3: After you know the line you wish to replace, note its "command offset" in OSA2. This is going to be the point in memory that you wish to overwrite.
Fighter.pac starts at offset: 80F9FC20 in RAM. So to find the true memory location you wish to overwrite, you ADD your command offset to 80F9FC20. A good tool to do this quickly: http://www.csgnetwork.com/hexaddsubcalc.html
So for the case of our code, I choose to inject over the very first line
07020000 of action 10C. This is a nice choice because it has no additional requirements and is not an if statement or else or anything else like that. Its command offset is 23AE0. So, doing the math on it, its true location in memory is: 80F9FC20 + 23AE0 = 80FC3700.
So because we will be replacing that line, 07020000, we need to put it back in our commands within our injection. So our injection code now looks like:Code Select
---DATA---
00000000 0000007C
00000006 0000003A
00000002 YYYYYYYY
00000002 ZZZZZZZZ
---Commands---
07020000 00000000
02010200 XXXXXXXX
Now we have a bit more work to do. We need to put a Go to command at the end of our commands to instruct to go back to fighter.pac:Code Select
00000000 0000007C
00000006 0000003A
00000002 YYYYYYYY
00000002 ZZZZZZZZ
07020000 00000000
02010200 XXXXXXXX
00090100 AAAAAAAA
Now, here is an important stepping point. Count how many lines we have here: 7. Each line takes up 8 bytes of memory. So to calculate a byte count, take 7*8, then convert to hex. Our byte count would be 0x38.
Now, I'm going to cheat a little and show you a tip on how to save memory. In a specific portion of fighter.pac, 0xBA6C, I found a line which already has Change Action: 7C, req=3A. I can use the parameters called by that command already, and save two lines of memory! The params as listed in OSA2 are at 0xBA2C, so doing the classic math gets me the following command:
02010200 80FAB64C
So now, our code:Code Select
00000002 YYYYYYYY
00000002 ZZZZZZZZ
07020000 00000000
02010200 80FAB64C
00090100 AAAAAAAA
With a new byte count of: 0x28
SECTION 4. HEADER
So now, lets keep pressing. We need to make the HEADER, and FOOTER. So I happened to know that 9019A500 was free in memory for at least 28 bytes (I'll post free areas in memory later).
So to go to 9019A500, I use the following command:
4A000000 DDDDDDDD
16EEEEEE 000000FF
DDDDDDDD is the initial pointer. You instruct it to point to 90000000.
EEEEEE is what you add to the pointer, in this case 19A500.
FF is the byte count.
So, the result:Code Select
4A000000 90000000
1619A500 00000028
00000002 YYYYYYYY
00000002 ZZZZZZZZ
07020000 00000000
02010200 80FAB64C
00090100 AAAAAAAA
Now we need to add in the footer. Remember that area in memory I told you to remember where the command 07020000 was? 80FC3700.
We remove the first two numbers with a pointer to 80, 06.
The result:
06FC3700 000000FF
Where FF is the byte count of how many lines we are replacing in fighter.pac (in this case, 1, with a Go to command).
The result:Code Select
06FC3700 00000008
00090100 GGGGGGGG
Now, lets add it all together:Code Select
4A000000 90000000
1619A500 00000028
00000002 YYYYYYYY
00000002 ZZZZZZZZ
07020000 00000000
02010200 80FAB64C
00090100 AAAAAAAA
06FC3700 00000008
00090100 GGGGGGGG
So now for the part where good organization pays off. I strongly recommend you this in excel as long codes need good organization.
I did this already, so please observe:
Our first data line sits at 9019A500 which happens to be one of our go to commands parameters.Code Select
Taunt Canceling v2.1 [Shanus,Camelot,WindOwl]
IGNORE00 4A000000 90000000
IGNORE00 1619A500 00000028
9019A500 00000002 [COLOR="SeaGreen"]80FC3708[/COLOR] Area to return
9019A508 [COLOR="Orange"]00000002 9019A510[/COLOR] Start of code
9019A510 07020000 00000000 Line I overwrote
9019A518 02010200 80FAB64C Change Act: 7C, req=3A
9019A520 00090100 [COLOR="SeaGreen"]9019A500[/COLOR] Go to return
IGNORE00 06FC3700 00000008
IGNORE00 00090100 [COLOR="Orange"]9019A508[/COLOR] Go to start
So, notice that I populated memory addresses and color coded. My Go to return in fighter.pac is where I overwrote + 8 bytes since I want to return 1 line later than I overwrote. My other go to location points to the parameter which points to the START OF THE COMMANDS.
So to make it clear, here is how this code truly works:
Taunt action is called when you press taunt.
At the beginning, instead of running 07020000, we overwrote it with the [COLOR="Orange"]orange Go to line[/COLOR]. This points to our parameter which says to go to the start of our commands. From there, it runs 07020000 and the change action command when near edge. Then it runs the [COLOR="SeaGreen"]green Go to[/COLOR] command to return back to the line after I replaced in fighter.pac.
So now that we know how long our code will take in memory, we need to find an area which is unoccupied.
Yes, that code works for taunt cancels. However, you'll need codes to allow taunts during dashes and runs to make it behave like 64 smash. You'll need to wait for Project M for those ;-)
Free memory:
93573000 - 935E0000
Quote from: NAMQ_DrunkeNFeasT;10574697How can I skip the step in red, idk how to use that method of saving lines, and I think it should matter to save lines, as, with have more than 8,000 lines of code for ourselves
plz shanus, help me with this one :(
00000000 0000007C
00000006 0000003A
this was on the code, but after that step, it was gone, and that was the data for the code to go to the change action to teether animation
the code was like this:
00000000 0000007C
00000006 0000003A
00000002 YYYYYYYY
00000002 ZZZZZZZZ
07020000 00000000
02010200 XXXXXXXX
00090100 AAAAAAAA
after the step it went to be like this:
00000002 YYYYYYYY
00000002 ZZZZZZZZ
07020000 00000000
02010200 80FAB64C
00090100 AAAAAAAA
EDIT:
you said we needed to count the lines and do (#of lines)*8 but, idk what can I do if I skip that step on decreasing the lines
I hope you can understand this, I want to implement something, but I need to understand on how to skip this step if in fighter.pac what I want is not in memory
and another thing, that example is great shanus, and you also labeled the code in the final part of the post, which is awsome :)
But what if, I don't have a change action only? how would I add more, like, an IF: command, along with a change action and an Else IF?
here is what I want to make:
Cancelable Smash Charge with Shield and Opposide direction than the one facingCode Select
IF: Button is Pressed: 0
Change Action: 20 = Requierement IF Button Press 3
Additional Requierement: Compare: IC-Basic[243] >= IC-Basic[77]
End if:
How would I code that? if you can help me man, I can atleast start making my own codes for public
EDIT 2:
the code will be something likeQuote
IF: stuff
---DATA---
00000006 00000030
00000000 00000000
---Command---
000A0200 XXXXXXXXQuote
Change action stuff
---DATA---
00000000 00000020
00000006 00000030
00000000 00000003
---Commands---
02010300 XXXXXXXXQuote
Additional Requierement stuff
----DATA----
00000006 00000007
00000005 (no idea here, as it needs to be memory type "Internal Constant". Type "Basic". Variable # " 1011")
00000000 00000004
00000005 (Same as the second line, only that the Variable # is now "3149")
---Commands---
02040400 XXXXXXXXQuote
End If:
---DATA---
00000000 00000000
---Commands---
000F0000 XXXXXXXX