Tutorial A basic guide for Gateshark to NTR translation

Did this Guide help you?

  • Yes, I did a working plugin!

    Votes: 7 50.0%
  • Yes, but I had some questions unanswered

    Votes: 4 28.6%
  • Yes, but I needed help from the comments

    Votes: 0 0.0%
  • No, but I learned something nevertheless.

    Votes: 3 21.4%
  • No.

    Votes: 0 0.0%

  • Total voters
    14

Deleted member 369977

Felyne Hunter
OP
Member
Joined
Aug 16, 2015
Messages
383
Trophies
0
XP
346
Country
Germany
Hello,
I've been seeing a lot of people attempt their luck at creating NTR Cheatplugins and I see the same naive mistake over and over. Please refer to the following picture:
d0a167f1c42e4d5b263dd85988deb5cc.png
But, before we begin I think I should explain the gateshark format a bit, since most people don't seem to understand it.

Warning, this post might get a little bit technical. This tutorial requires to read a lot and utilize C. If you don't know how to code in C, learn it first. I won't answer any basic questions about this programming language. ( Google is always helpful ) Also you should've already taken a look at the demo plugins @cell9 provided to us to understand how these work.

I'd advise you to declare a uint32 variable called offset for simplification and direct translation. If you want to advance even further you have to think a bit more then just this tutorial :)

So a gateshark code is made out of multiple smaller codes, which can read, write and compare RAM from the Nintendo 3ds. All Gateshark codes follow this pattern:
Code:
ZXXXXXXX YYYYYYYY
except for the 0xD codes, which are the following:
Code:
ZZXXXXXX YYYYYYYY

Z is the operation that shall be executed. For a full list take a look here
X is the offset for the RAM.
Y is the Data used for this code.

Alright, now how do we translate these codes?

The most basic Gateshark codes are the 0x0, 0x1, and 0x2 codes, which are used to write RAM.
The 0x0 Code write a 32 bit Integer value at the address X + Offset,
Code:
0XXXXXXX YYYYYYYY--> WRITEU32(XXXXXXX + Offset, YYYYYYYY);
This means write Integer Y to X + Offset.
We can represent that in C by:

The 0x1 Code write a 16 bit Short value at the address X + Offset,
Code:
1XXXXXXX 0000YYYY--> WRITEU16(XXXXXXX + Offset, YYYY);
This means write Short Y to X + Offset.

The 0x2 Code write a 8 bit Byte value at the address X + Offset,
Code:
2XXXXXXX 000000YY --> WRITEU8(XXXXXXX + Offset, YY);
This means write Byte Y to X + Offset.

Please note that you should always try to minimize the amount of bytes you want to write, or else there might be some (negative) sideeffects.

Next are the Gateshark codes to compare RAM. Comparing Integers is from 0x3 to 0x6 and comparing Short are from 0x7 to 0xA. Please refer to the wiki post here for further information about these codes. These are 'if'-statements.

After that we have another very important gateshark code, the 0xB code. This reads a 32 Bit integer value from the Ram and uses it as the new offset. This is used for Pointers. We can use
Code:
Offset = READU32(X+Offset);


The 0xC code is used for loops. The loop statement is executed Y times and ends with a 0xD1 command which increases the the offset by Y of the 0xD1 command. It's a basic 'For' loop.
Code:
C0000000 00000063 <- Start the Loop | Repeat 0x63 times.
**some other instructions*
D1000000 00000010 <- End the loop and increase the offset by 0x10 bytes
Most people use the 0xDC code in front of a 0xD1 code to increase the offset ( I'll come back to this one later ), but it isn't necessary, as you can increase it in the 0xD1 block.

And now to the 0xD codes. There are a lot of these codes. ( 14 to be exact ), but we will only be focusing on the more important codes. The 0xD0, 0xD2, 0xD3, 0xDC and the 0xDD code.
The D0 code closes the latest conditional statement (0x3 to 0xA codes ), just like we would close our conditional statement in C.
The D2 code closes all if statements and escapes a 0xC loop.
D3 is a very commonly used code. Most people use it at the beginning of their gateshark code to declare the offset. However this one if not necessary if the Y block in all 0.
To increase an offset you use the DC block. It increases the offset by Y.
And last the DD code. A new code introduced by gateshark. It's used to test for button combinations. Close it with a D0 code. I'd recommend using a menu for plugins though. If you want to use keys anyways - A quick google search will give you your needed information. ( or just look at some other plugins :) )

And we are done. If you have any questions regarding parsing gateshark to NTR take a look at this small wiki post first. It has a collection of all gateshark codes. Including the not mentioned dxData codes.

If you want to test a gateshark code if it works, but don't have a gateway card, feel free to use my fork of the NTR debugger which includes a gateshark tab. ( Please note, that not all codes will work. Codes that must be constantly executed like moonjumps, or similar can't be done using this ).

Credits:
@cell9 for his awesome work on NTR.
 

jdeath

Active Member
Newcomer
Joined
Oct 8, 2015
Messages
27
Trophies
0
Age
44
XP
76
Country
United States
Thanks. This was very helpful. By using a ! I could make a few cheats autostart (selecting item disables cheat)
 

quanta

Member
Newcomer
Joined
Jun 3, 2016
Messages
16
Trophies
0
Age
27
XP
95
Country
United States
Thanks for this, especially the git. If you know basic programming you can pretty much implement everything. However, can you give a basic rundown on DxData? I saw some codes that I wanted to convert that implemented it but the values made no sense.
 

Deleted member 369977

Felyne Hunter
OP
Member
Joined
Aug 16, 2015
Messages
383
Trophies
0
XP
346
Country
Germany
From what I understood DxData is just a separate variable that can be written to any address. I haven't really been able to test these codes yet, since I hadn't found any easy codes using DxData. Therefor I might be wrong with my documentation.

But let's try to write to an arbitrary inventory where every item is 4 bytes long. the first 2 bytes are the ID, we'll use DxData to write that. and the second 2 bytes are the amount which we will lock to 99 ( 0x0063 )

So first we will set the offset for the first item, then create a loop with the 0xC command.
Code:
D3000000 08123456  <- Replace the Y block with any valid offset
D5000000 00000000  <- Set the DxData to 0
C0000000 00000032  <- Create a loop
D4000000 00000001  <- Add 1 to the DxData (?) Not sure. That's why I'd need to test it more. ( Maybe I could use an old GBA ar to test this )
D7000000 00000000  <- Write our DxData ( ID ) and increases the offset by 2.
10000000 00000063  <- Write the amount of 99
D1000000 00000002  <- End the loop | Increase the offset by2

So to parse this code just declare a new variable according to the size of our dxData. In our case it would be u16, since we only use a Short. I wouldn't make this variable global, but rather specific to the parsed code.
 
  • Like
Reactions: quanta

Deleted member 369977

Felyne Hunter
OP
Member
Joined
Aug 16, 2015
Messages
383
Trophies
0
XP
346
Country
Germany
WOW. thanks this was really really helpful :yay: .Though, I do still need help on one thing. The wiki post you linked doesn't show 0xE codes. Could you please show me how one would convert 0xE codes to ntr?
0xE codes? Never heard about these. Mind posting a code with said code and what the code is supposed to do?
 

LackieG4002

Member
Newcomer
Joined
Jun 23, 2016
Messages
5
Trophies
0
Location
Somewhere in the land of California
XP
56
Country
United States
I came across a code that i wanted to convert to ntr and it's suppose to stop monster encounters.

Code:
D3000000 00000000
E02CC620 00000028
E2841F7D E59F001C
E5900000 E5900000
E5900004 E3100C02
03A00000 15940204
E5840200 E12FFF1E
002CC648 00308164
001D077C EB03EFA7

So, I started reading an explanation about 0xE codes but I didn't really get it. Hopefully you'll be able to understand it :D

EXXXXXXX YYYYYYYY - Patch Code
Parameters: address (XXXXXXX), Number of Bytes (YYYYYYYY)

This code type was introduced in gateway 3.6.2, but the implementation is a bit iffy. I believe Gateway may have botched this one up slightly. This code writes YYYYYYYY bytes from the list of following values (an example will make this a bit clearer, please bear with me) starting at the address (+offset we might have set). Where this code gets a bit iffy is the endianness it treats the list of values to write:

Warning: Spoilers inside! D3000000 32C825A4 - sets the current offset to 0x32C825A4
E0000000 00000008 - write the following list of 08 (0x10) bytes to the addresses 0x32C825A4 onwards
44332211 88776655 - this is the part the code goes iffy. 0x11 is the value that gets written to 0x32C825A4, 0x22 gets written to 0x32C825A5, 0x55 to 0x32C825A8, 0x66 to 0x32C825A9 etc.

Logic would usually dictate that it should not treat the list as individual 32-bit strings but simply a stream of bytes to write, but it does. So this code is to be used very carefully as to write the proper value to the addresses we want. It's not broken per se, it's just a bit tricky to bend your mind around the stream of bytes.

The 0xE code type will also disable code type detection for YY of bytes in the code list. I.e. in the above example the line following E0000000 00000008 would simply be interpreted as a list of values, not an 0x4 (32-bit 'greater than' conditional) code type.
 

Deleted member 369977

Felyne Hunter
OP
Member
Joined
Aug 16, 2015
Messages
383
Trophies
0
XP
346
Country
Germany
I hope I understood that code, but I honestly have no clue how to explain it since I for myself just barely understood this right now.

Alright, so the first line sets an offset to 0, ( so we can just ignore this line.. )
Then comes our 0xE code. It uses the offset 0x2CC620 and the next 28 bytes specified in the code ( the next 3 1/2 lines.. [ each block is 4 bytes , and 28 / 4 = 7, so 7 blocks which is 3 1/2 lines] ) So our array of bytes should be E2841F7D E59F001C E5900000 E5900000 E5900004 E3100C02 ( please reverse every block to LE so it works, I'm just a bit lazy right now )
And this array of bytes is written to the offset 0x2CC620 until 0x2CC648.

What I don't understand is the then unused block of 4 bytes: 15940204 ( line 6, Block Y ).

Same with the next 0xE command, there is again a byte unused.
Sadly I don't own a gateway card. ( my primary reason why I made my debugger btw :P ) So I can't confirm anything. Maybe if you ask somebody with a gateway card he could help you by doing some tests in an unused memory region.
 

Blurro

Active Member
Newcomer
Joined
Oct 10, 2016
Messages
28
Trophies
0
Age
24
XP
258
Country
hay im trying to convert fishguys 0xE code, but there isnt anywhere showing how to convert it... wondering if you could help. the code is
D3000000 00000000
002F1078 ED901A97
002F1084 E1A00000
DD000000 00000400
002F1078 EA0BE9F8
E05EB860 00000010
E59F7004 EE017A10
EAF41603 C2400000
D2000000 00000000
D3000000 00000000
00233D28 EA0EDEC3
E05EB83C 00000024
E92D0020 E22AAB01
E20A5B01 E3550B01
1A000000 E22AAB01
E8BD0020 E587A000
EAF12132 00000000
D2000000 00000000
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    Psionic Roshambo @ Psionic Roshambo: https://youtu.be/twsR-I14wfI?si=hYfXUIKsM869LGF-