How to port more complex codes with non standard porting
#1
How to port more complex codes with non standard porting




NOTE: This Tutorial is for intermediate to advanced coders. Beginners should view THIS Tutorial first.


Introduction

When porting more complex codes with auto porters, it can happen that the finished codes do not work or crash the game. Then this code will almost certainly need non-standard porting.

Non-standard porting is when not only the hook address has to be ported, but there are also addresses in the (ASM) code that have to be ported. These can be pointers or in-game functions, for example. Non-standard porting is more time-consuming, as it is more difficult to find the ported address. Especially if it is in an environment that also contains function addresses or pointers.

This tutorial will show you some attempts how to port such codes.

What you will need:
-This Forum
-Hex Editor (I will choose online hex Editor HexEd.it)
-Decent knowledge about ASM (some instructions, see THIS tutorial how to learn ASM)
-RAM Dumps (you neet at least the RAM Dump of the region the code is from and the region you want to port to, see THIS tutorial how to get RAM Dumps)
-Disassembler (I will use online Disassembler disasm pro)
-{Optional} Hex Calculator

 


Chapter 1: The Code we want to port

For our test I have chosen a code that is not finished porting yet, it is called "Item Effect Randomizer" by TheLordScruffy. The code is given in PAL region and we want to port it to NTSC-U.

Here is our code in PAL:

Code:
C257276C 00000024
7D8C42E6 718B00F0
718C000F 3CA0809C
80A5D728 80A50B70
2C050003 4082001C
2C0C000D 38600001
418200F4 2C0C000E
40820008 39800008
2C0C000E 40820010
2C0B0080 40800008
39800008 2C0C000C
38600006 418200C8
2C0C0009 38600007
418200BC 2C0C0005
3860000B 418200B0
2C0C000F 3860000C
418200A4 48000015
00010204 09070803
0B060C0D 0A0F0E00
7CE802A6 7E038378
3D00809C 610836B8
7CE760AE 1CE7001C
7D88382E 2C0C0000
40820028 3D00808B
61085468 1CEC000C
7D874214 3CA08002
60A51450 7CA903A6
4E800421 48000048
80D00004 3C80809C
80843618 80840014
38600000 80A40000
7C053000 41820018
38840248 38630001
2C03000C 41820014
4BFFFFE4 7C832378
7D8903A6 4E800421
3860FFFF 00000000



Chapter 2: Finding Location of the Hook adress in RAM

What we want to do is find the Code's RAM Address (offset & column location) within the RAM Dump. To figure this out, simply remove the first 2 digits off the first line (the C2, 06 or 04 line) of the code.  If you did the conversion correctly, you should come up with a value of "57276C".

Now open HexEdIt and open your PAL RAM dump with the option "open file". On the right you find "go to". Click on the box and type in the adress with "0x" as prefix. Click Enter.

[Image: NSPTut-P01.png]

You should navigate to the adress now, that means the cursor should be at this adress.


Chapter 3, Section 1: Decide which bytes to search for

To find the correct adress on other region RAMs, you need to decide for what bytes you want to search for. Some good instructions are cmpwi, li, stw, sth, mulli or also mr. Bad instructions to search for are bl (function calls), lwz (sometimes, not always), lis. The reason why this instruction are bad to search for is that they vary in different ports and you will not be able to find the correct adress.

So before we continue, let's disassemble the environment of this adress. I will choose the bytes from 0x572740 to 0x57279F.

The 4 bytes at our adress are 4BAAECE5. This is a bl instruction, which means that is likely to be a function call. So this is not a good instruction to search for. But we have some mulli and mr instructions in a row, so lets take the three instructions

mr r3, r16
mr r4, r31
mulli r0, r0, 0xc

to search for, in bytes that would be 7E0383787FE4FB781C00000C starting at adress 0x0057275C. That will be our bytes to search for.

[Image: NSPTut-P02.png]


Chapter 3, Section 2: Searching the bytes

Now we search this bytes in the NTSC-U RAM Dump. Open this Dump. On the right of HexEdIt you will see a "search for" box, type* this bytes with spaces in. Then make sure only "Hexadecimal Values" is checked on Data Types and "List all occurences" is also checked.

[Image: NSPTut-P03.png]

Finally click on "Search now" - You should find one adress.

0x0056D90C

*NOTE: Seems like HexEd.it has no copy Function, so you have to type the bytes, but that shouldn't be a problem at all.

That means we found one adress matching with our bytes. Now we want to get our ported adress, for this, we need first the difference of our search start adress and our adress we want to port. The adress we want to port is 0x0057276C, and our search start adress was 0x0057275C, means that our port adress is 0x10 bytes after the search start adress.
Now we have found the adress matching with our bytes. To get our ported adress (which is 0x10 after the adress of our bytes), we add the difference of 0x10 and find our adress:

0x0056D91C

Navigate to this adress in HexEd.it. You will see the Bytes 4BAB2FD5. This is a bl instruction and means that we probably found the correct adress.
I will tell you that this is our hook adress ported to NTSC-U!


Chapter 4: Find addresses contained in the ASM code

We already have our hook adress ported. Now we want to port the adresses in the ASM code. Before we can do this, we have to find them before. For this, we need to disassemble our code.

Code:
mftb r12, 0x10c
andi. r11, r12, 0xf0
andi. r12, r12, 0xf
lis r5, 0x809c
lwz r5, -0x28d8(r5)
lwz r5, 0xb70(r5)
cmpwi r5, 3
bne 0x38
cmpwi r12, 0xd
li r3, 1
beq 0x11c
cmpwi r12, 0xe
bne 0x38
li r12, 8
cmpwi r12, 0xe
bne 0x4c
cmpwi r11, 0x80
bge 0x4c
li r12, 8
cmpwi r12, 0xc
li r3, 6
beq 0x11c
cmpwi r12, 9
li r3, 7
beq 0x11c
cmpwi r12, 5
li r3, 0xb
beq 0x11c
cmpwi r12, 0xf
li r3, 0xc
beq 0x11c
bl 0x90
.word 0x00010204
.word 0x09070803
.word 0x0B060C0D
.word 0x0A0F0E00
mflr r7
mr r3, r16
lis r8, 0x809c
ori r8, r8, 0x36b8
lbzx r7, r7, r12
mulli r7, r7, 0x1c
lwzx r12, r8, r7
cmpwi r12, 0
bne 0xd8
lis r8, 0x808b
ori r8, r8, 0x5468
mulli r7, r12, 0xc
add r12, r7, r8
lis r5, 0x8002
ori r5, r5, 0x1450
mtctr r5
bctrl
b 0x11c
lwz r6, 4(r16)
lis r4, 0x809c
lwz r4, 0x3618(r4)
lwz r4, 0x14(r4)
li r3, 0
lwz r5, 0(r4)
cmpw r5, r6
beq 0x10c
addi r4, r4, 0x248
addi r3, r3, 1
cmpwi r3, 0xc
beq 0x118
b 0xec
mr r3, r4
mtctr r12
bctrl
li r3, -1


Most ASM or string write codes that will load adresses (of functions or pointers) that need to be ported have the following structure:

lis rX, 0x80GG
lwz rY, 0xSIMM(rX)
or
lis rX, 0x80GG
ori rY, rX, 0xUIMM

where GG can be from 02 to 9C, rX and rY arbitary GPR. That means a lis instruction followed by a lwz or an ori instruction mostly indicates function calls or the use of pointers. If we search for these in our disassembled code, we find 5 occurences:

1.
lis r5, 0x809C
lwz r5, -0x28D8(r5)
2.
lis r8, 0x809C
ori r8, r8, 0x36B8
3.
lis r8, 0x808B
ori r8, r8, 0x5468
4.
lis r5, 0x8002
ori r5, r5, 0x1450
5.
lis r4, 0x809C
lwz r4, 0x3618(r4)

That means these five adresses needs to be ported now.

0x809BD728
0x809C36B8
0x808B5468
0x80021450
0x809C3618


Chapter 5. Using the Forum as help

If you are lucky, some of the codes of the forum have already used (and ported) adresses. For example, if you use the forum search for "D728", you will look at the sources of other codes that this pointer is called "race_data".
Indeed, the first two adresses and the last adress were already used by other codes. We can extract these adresses e.g. from my "Call Item Function Anytime" code. The NTSC-U adresses are:

PAL --> NTSC-U

0x809BD728 --> 809B8F68 (race_data)
0x809C36B8 --> 809BEEB0 (item_functions)
0x809C3618 --> 809BEE20 (player_holder)


Chapter 6. Porting the rest

Two adresses are missing, and we need to port them manually. The adress 808B5468 is harder to port. If you go to this adress you will see the bytes 00000000, but also surrounding values starting with 0x80.

[Image: NSPTut-P04.png]

That means these are most likely function adresses, and a search with these values on other RAM Dumps will not work. Also, there is no ASM code in environment. So what you can do is to scroll up or down a bit, to find either assembly or some text. If you scroll down a bit you will notice some text appearing, starting with

"FSqrt: Input is..."

[Image: NSPTut-P05.png]

Ok, we have a string at starting adress 0x808B56D0 we can search for. Do a search for at least 6 of the bytes on the NTSC-U RAM Dump, so we do a search for "46537172743a".

If you do this you should come up with 13 occurences. Obviously, if there is more than one occurence, it will be hard to find the correct one.

[Image: NSPTut-P06.png]

To do so, run the search on the PAL RAM Dump too. The occurences are listed in order, so take a look at the position of your adress. You will notice: On PAL, the first occurence holds the bytes you use to search.

[Image: NSPTut-P07.png]

That means: On NTSCU Dump, also the first adress 0x008B0F98 is the one we want to look at. Now to get our ported adress, we need to calculate the difference of our search start adress and our adress we want to port, like in Chapter 3 again. This is a bit harder, you might need a hex calculator for this.

You will find the difference of -0x268. If we now add this to our found adress 0x008B0F98, we get the result 0x008B0D30, so 808B0D30 is our ported adress.

To check it, open NTSC-U dump and look at the adress 0x008B0D30, you will find 00000000 as bytes after a bunch of 0x80 adresses, so chances are high that this is the correct adress.


The adress 80021450 is easier to port, so you might try this one alone. HINT: Use the 12 bytes at adress 0x002145C in PAL dump as search bytes.

If you have done all correctly, you must find 800208F0 as the correct adress.


Chapter 7: Setup the Ported code

So we have all adresses ported now.

0x8057276C --> 0x8056D91C (hook adress)
0x809BD728 --> 0x809B8F68 (race_data)
0x809C36B8 --> 0x809BEEB0 (item_functions)
0x808B5468 --> 0x808B0D30
0x80021450 --> 0x800208F0
0x809C3618 --> 0x809BEE20 (player_holder)


To setup the new ported code, replace all the old adresses with the new adresses, be careful to also replace the lis-instructions.

[Image: NSPTut-P08.png]


Chapter 8: Testing

Now test the code on console and on dolphin to make sure it works. If the code isn't working or crashing, you have either made a mistake when porting or you have overlooked an address that needs to be ported. Then look at the code again and check whether you may have made a mistake or overlooked something.



Conclusion


Two main problems occur with porting more complex codes:

1. Find the instructions that will need porting
2. When attempting to port, choose the correct bytes to search for

I hope this tutorial helps you to figure these two things out in future and with that to port more complex code to other regions, as auto porters do not support (yet) non standard porting.


Happy Coding!


Tutorial written by: Unnamed; Credits: Vega for further tutorials
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)