[Guide] How to create Gateway Cheat Codes

Discussion in '3DS - Tutorials' started by Localhorst86, Jan 18, 2016.

Jan 18, 2016
  1. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    Gateway cheats seem like magic. How can a seemingly random string of numbers give us infinite lives in Super Mario 3D Land or make us invincible? It's simple. They access our machines RAM that holds our game information and manipulate bytes to do what we want. They can be viewed as a very rudimentary form of programming language, but one that is mighty powerful.

    In this "quick" guide I am going to explain the different code types that are implemented in the Gateway cheat engine, what the codes do and how we construct them. In order to understand the codes and prevent any misunderstandings we need to define the terminology first, so here's a list of words that I will be using throughout the tutorial. I will also be giving alternative terminology that might be used in other areas of computing, but for the sake of this tutorial we are going to stick with the terminology that is marked in bold.

    Note beforehand: We are going to be dealing a lot with hexadecimal numbers when creating codes (base 16). Since we mainly use the decimal system in our daily lives we will have to calculate between decimal and hexadecimal (or vice versa) quite often. Whenever I am using a hexadecimal number, it will be denoted by a leading '0x'. This will help us to not confuse hexadecimal values that look like decimal values (like 0x10 for example) with their decimal sibbling (10). So when you see a regular number like '10', that will be decimal. If it's 0x10, it's hexadecimal (0x10 = 16, fyi). 0b will be used for denoting binary numbers (only used in the 16-bit conditional codes).


    Code: A code consists of various parameters. Parameters are 'code type', 'address', 'value', 'offset' 'mask' and 'data register'. A code is split into two 8-digit strings separated by a space.

    Code Type: Determines what the code does. The first digit of a code determines the code type, note that some code types (like the D codes) can be further split into secondary code types, which will be determined by the second digit of the code. Gateway supports 28 different code types, 27 of which gateway has documented.

    Address: the games memory is laid out in bytes, each byte represented by an individual address and performing a specific task within the games memory. We can precisely define which byte we want to manipulate by telling the Gateway cheat engine the exact address of the byte. I common computer terminology an address is often called 'offset', but we are going to need that term for something else so we will be calling addresses strictly by the name 'address'.

    Value: This is the value of a specific byte in the games memory. For example the address that holds your ammount of lives in Super Mario 3D Land has a value corresponding to this number. Often called 'data'. To avoid confusion with the 'data register' only the term 'value' will be used.

    Offset: Since the first digit of a code line is always reserved we might – depending on the code type – not be able to enter an 8-digit address into a code. If the address we want is more than 7 digits, we need to set the offset to a value that, when added to the address paramter, adds up to our correct 8-digit address we want to manipulate.

    Mask: Only used in 16-bit conditional instructions. It allows us to 'mask' individual bits in the condition – comparable to wildcards. This will be clearly explained at the 16-bit conditional section.

    Data register: a specific register that can hold a value and add to that value. By default it is 0x0 but we can set it to any value we want or load a value from any address. Specific code types are used for loading a value from an address or writing the value within the data register to an address.


    So without further ado, here are the code types:

    Memory Writes:
    parameters: address (XXXXXXX), value (YY, YYYY, YYYYYYYY)
    To write an address higher than 0xFFFFFFF, you need to set an offset using code Type 0xD3. The offset gets added to the address parameter to determine the final address we want to manipulate. See Code type 0xD3 for further instructions.

    The memory write codes are split into three code types. Which code type is used depends on the value you want to write. One byte can hold 256 values, two bytes can hold 256² values, four bytes can hold 256^4 values, including 0. So the maximum value a write instruction can write is:

    8-bit : 255
    16-bit: 65.535
    32-bit: 4.294.967.295
    If the game stores a value as 8-bit, doing a 16-bit or 32-bit write to the address might break the game or manipulate other values of the game that we might not intent to change. As an example, „Legend of Zelda: Tri Force Heroes“ stores the ammount of the items we have in 70 consecutive bytes, so doing a 16-bit write to such an address will also modify the item next to the one we wanted to change. So be carefull to only manipulate as little as neccessary, but as much as required.

    0XXXXXXX YYYYYYYY – 32bit write to [XXXXXXX + offset]
    writes the 32-bit value we specify to the given address. This manipulates four bytes starting at the given address. Two 16-bit writes can be used with the same result, endianness has to be taken into account. See Note at the end of the tutorial about endianness.

    1XXXXXXX 0000YYYY – 16bit write to [XXXXXXX + offset]
    writes the 16-bit value we specify to the given address. This manipulates two bytes starting at the given address. Two 16-bit writes can replace a 32-bit write, however endianness has to be taken into account. See Note at the end of the tutorial about endianness.

    2XXXXXXX 000000YY – 8bit write to [XXXXXXX + offset]
    writes the 8-bit value we specify to the given address. This manipulates a single byte. Two 8-bit writes can replace a 16-bit write, however endianness has to be taken into account. See Note at the end of the tutorial about endianness.

    Examples:
    Warning: Spoilers inside!

    Conditional 32bit codes:
    parameters: address (XXXXXXX), value (YYYYYYYY)

    Conditional codes allow us to compare the value of an address to the value we provide as a parameter. If the condition is true execution continues at the next code line. If false, execution will jump to the next terminator code (Code type 0xD0 and 0xD2) and continue from there. Conditionals can be nested. The code does not manipulate the games memory on it's own, it needs to be followed by a code that does the manipulation (a 32-bit write for example).


    3XXXXXXX YYYYYYYY – Less Than (YYYYYYYY < [XXXXXXX + offset])
    If the value at the specified address is less than the value we provide, continue the instruction.

    4XXXXXXX YYYYYYYY – Greater Than (YYYYYYYY > [XXXXXXX + offset])
    If the value at the specified address is greater than the value we provide, continue the instruction.

    5XXXXXXX YYYYYYYY – Equal To (YYYYYYYY == [XXXXXXX + offset])
    If the value at the specified address is equal to the value we provide, continue the instruction.

    6XXXXXXX YYYYYYYY – Not Equal To (YYYYYYYY != [XXXXXXX + offset])
    If the value at the specified address is not euqal to the value we provide, continue the instruction.

    Examples:
    Warning: Spoilers inside!

    Conditional 16bit deref + write codes:
    parameters: address (XXXXXXX), value (YYYY), mask (ZZZZ)
    Even though Gateway calls them write codes, according to the Datel trainer toolkit manual for the AR DS and my trials these do not write to the location. It needs to be followed by a code that does the manipulation (a 16-bit write for example). The mask parameter allows us to mask out specific bits of the 16 bit value for the condition. If the mask is set to 0x0000 the code will behave exactly like the conditional 32-bit codes (Code types 0x03-0x06).

    7XXXXXXX ZZZZYYYY – Less Than
    If the masked value at the specified address is less than the masked value we provide, continue the instruction.

    8XXXXXXX ZZZZYYYY – Greater Than
    If the masked value at the specified address is greater than the masked value we provide, continue the instruction.

    9XXXXXXX ZZZZYYYY – Equal To
    If the masked value at the specified address is equal to the masked value we provide, continue the instruction.

    AXXXXXXX ZZZZYYYY – Not Equal To
    If the masked value at the specified address is not equal to the masked value we provide, continue the instruction.

    Understanding masks is a bit tricky and from the top of my head I can't really think of a reasonable practical use of a masked conditional but i'll try my best to explain them. If you think you can provide a clearer explanation of masks, feel free to post it, I can insert it here if you like.

    Masks work on a binary/bit level. A mask of 0x0000 will translate to 0b00000000 00000000 (space added for better readability), 0xFFFF will translate to 0b11111111 11111111. Any bit set to 1 will be ignored when comparing the value at the address provided with the value we pass in the code.

    Let's say when our character does a regular jump the value at address 0x03BA110C changes to 0x25 but when we do a running jump it changes to 0x15. Address 0x03BA110E determines the gravity and we want to set it to zero every time we jump, regardless if we made a regular jump or a running jump. A code 93BA110C 00000005 (mask = 0x0000) would only be true for a regular jump, not a running jump. Thats why we want to mask out any bits that we consider irrelevant for our condition. To do that we have to translate 0x25 and 0x15 to binary first:

    0b00000000 00100101 = 0x25
    0b00000000 00010101 = 0x15

    we want the condition to be true whenever the value ends with 0x5 so we translate that to binary:

    0b00000000 00000101 = 0x5

    we mask out all the bits that we do not care about with a 0b1 and convert it to hexadecimal

    0b11111111 11111000 = 0xFFF8

    This mask will only take the last 3 bits of the value and compare it to the last three bytes of our value that we pass in the code. So in our example, whenever the last three binary digits of our value matches 0b101 (0x5) the condition holds true and we continue to the next code line. If it is false we jump to the next 0xD0 or 0xD2 code.

    Examples:

    Warning: Spoilers inside!

    Offset Codes:

    Since for a lot of codes only a 7-digit address can be parsed we often need to add an offset to that address parameter to determine the final address. We have a few types of codes dealing with offsets. The rule is always: address parameter + offset = destination address.

    D3000000 XXXXXXXX – set offset to immediate value
    parameters: offset (XXXXXXXX)

    This will set the offset to an immediate value we pass in the code. This value gets added to any address parameter in all other code types to result in the destination address so in order to write to addresses with 8-digits it is necessary to set an offset. It is also quite common to set the offset to the destination address and work with the address parameter 0x0000000 in all other codes. This method, in my opinion, has a few advantages so in my codes you will usually see me declaring an offset everytime, even if it would not be necessary.

    Examples:
    Warning: Spoilers inside!
    DC000000 XXXXXXXX – Adds an value to the current offset
    parameters: value (XXXXXXXX)

    This code type allows you to increase the offset by the hexadecimal value you provide. This is particularly useful in combination with the loop code (see code type 0xC0) to manipulate a lot of addresses laid out in a repeating pattern with only a few lines of code.

    Examples:
    Warning: Spoilers inside!

    BXXXXXXX 00000000 – offset = *(xxx)
    parameters: address (XXXXXXX)

    This code type allows us to load a 32-bit value from the address we provide (+ any offset we might have set before) into the offset register, replacing the current offset. This allows us to use pointers in our code. For a tutorial on how to find pointers, see http://www.maxconsole.com/maxcon_forums/threads/293146-Finding-Pointer-Codes-With-Gateway-RAM-Dump (thanks to @json,for pointing towards that tutorial)

    Example:
    Warning: Spoilers inside!

    Loop Code:
    C0000000 YYYYYYYY – Sets the repeat value to ‘YYYYYYYY’

    parameters: number of loops (YYYYYYYY)

    This code allows us to repeat the following block of codes as often as we need it to. When code type 0xD1 or 0xD2 is hit, the loop number will decrease by 0x1 and start again. Combined with other codes we can manipulate a huge array of addresses with just a few lines of code.

    Example:
    Warning: Spoilers inside!

    Terminator Codes
    D0000000 00000000 – End If instruction
    This code ends the current conditional cod instruction. For examples see the section about conditional codes

    D1000000 00000000 – End repeat instruction
    This code decreases the current loop counter by one and returns code execution to the last 0xC0 code. See Loop code for examples.

    D2000000 00000000 – end code instruction. (not documented by team gateway)

    This code decreases the current loop counter by one and returns code execution to the last 0xC0 code. It also ends any conditional blocks. It also clears the current offset and any value you might have written to the data register. It is recommended to use this as final code terminator before starting a new code.


    Data Register Codes:
    The data register allows us copy a value from an address and manipulate it before writing it back to an address (either the same address or any other one). The data register is always 32-bit, we can decide on the “bit-ness” during the write instructions. If not set or loaded by any code, it will be 0x0.

    D5000000 XXXXXXXX – Sets the data register to XXXXXXXX
    parameters: value (XXXXXXXX)

    This code allows us to set the content of the data register to any arbitrary value we want.


    D9000000 XXXXXXXX – (32bit) sets data to [XXXXXXXX+offset]
    parameter: address (XXXXXXXX)

    This will load the 32-bit value from the address provided (also taking the offset into account) and store it in the data register.


    DA000000 XXXXXXXX – (16bit) sets data to [XXXXXXXX+offset] & 0xffff
    parameter: address (XXXXXXXX)

    This will load the 16-bit value from the address provided (also taking the offset into account) and store it in the data register.


    DB000000 XXXXXXXX – (8bit) sets data to [XXXXXXXX+offset] & 0xff
    parameter: address (XXXXXXXX)

    This will load the 8-bit value from the address provided (also taking the offset into account) and store it in the data register.


    D4000000 XXXXXXXX – Adds XXXXXXXX to the data register
    parameters: value (XXXXXXXX)

    This code simply adds the value we pass to the data register.


    D6000000 XXXXXXXX – (32bit) [XXXXXXXX+offset] = data ; offset += 4
    parameters: address (XXXXXXXX)

    This code writes the current content of the data register to the address provided (taking the offset into account) as a 32-bit value. After the write it automatically increases the current offset by 0x4.


    D7000000 XXXXXXXX – (16bit) [XXXXXXXX+offset] = data & 0xffff ; offset += 2
    parameters: address (XXXXXXXX)

    This code writes the current content of the data register to the address provided (taking the offset into account) as a 16-bit value. After the write it automatically increases the current offset by 0x2.


    D8000000 XXXXXXXX – (8bit) [XXXXXXXX+offset] = data & 0xff ; offset++
    parameters: address (XXXXXXXX)

    This code writes the current content of the data register to the address provided (taking the offset into account) as a 8-bit value. After the write it automatically increases the current offset by 0x1.

    Example for data register usage:
    Warning: Spoilers inside!

    Special Codes:

    DD000000 XXXXXXXX – if KEYPAD has value XXXXXXXX execute next block
    parameters: keypad value

    This code allows us to activate codes only as soon as a button combo is pressed. This is great for creating codes that can be enabled “on demand” by pressing the button combo that corresponds with the value we pass. Each button corresponds to a specific hexadecimal value. We just add any values of the buttons we want to be pressed for the button to activate. Let’s assume we want to press L+R+Start+Select, we just add 0x200, 0x300, 0x8 and 0x4. The result is 0x50C

    So by putting the line DD000000 0000050C in front of our code we will have to press the buttons to activate the code. The gateway cheat engine seems to be very sensitive about the button presses so sometimes the code will execute multiple times with even the shortest of a press of the button combo. See the following list for the available keys and their corresponding values. New 3DS exclusive buttons (ZL, ZR, C-Stick) are currently not available.

    Warning: Spoilers inside!

    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!



    Footnote about endianness:

    If you looked at a RAM dump of the 3DS - either in the built in hex editor or your PC - you might have noticed that when looking at a value at an address the values our codes write do not seem to match up. Thi is because the 3DS RAM is laid out in little endian, our codes are written in big endian. When we take the 32-bit big endian value 11223344 the cheat engine will split these up into four bytes, 11 22 33 44 then start by writing the least significant byte (44) to the address we want. then writes the next byte (33) to the following address. For further clarifcation, check the Wikipedia entry about endianness. For the sake of this guid:

    When you pass the value 1A2B3C4D in a code, it'll show up as 4D 3C 2B 1A in RAM. The value will be correct, though.

    Changelog:

    Warning: Spoilers inside!
     
    Last edited by Localhorst86, Jan 27, 2016


  2. GotKrypto67

    Member GotKrypto67 That one PHP guy

    Joined:
    Jul 21, 2015
    Messages:
    374
    Location:
    The Chamber of Kim
    Country:
    Korea, North
    You are a life saver. I had understood most of the gateway code creation, but this really wraps things up and answered all my remaining questions.
     
  3. dsrules

    Member dsrules GBAtemp Psycho!

    Joined:
    Sep 20, 2005
    Messages:
    3,507
    Country:
    @Localhorst86, I guess not many people noticed 3xxxxxxx is Less Than, not greater than
     
    Localhorst86 likes this.
  4. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    Thanks, I'll have to re-check that. I found conflicting documentation on the Internet so I went with what gateway said. I'll look into it.
     
  5. blax722

    Member blax722 GBAtemp Regular

    Joined:
    Sep 6, 2015
    Messages:
    100
    Country:
    Czech Republic
    You heard my prayers in the other thread, right? xD great work and thanks!
     
  6. DarkIrata

    Member DarkIrata GBAtemp Regular

    Joined:
    Jun 12, 2015
    Messages:
    296
    Country:
    Germany
    Nice tutorial! Would be cool to get add a archive of examples for unusual cheats. :)
    For example a way to decrease a value.
     
  7. Silent Hell

    Newcomer Silent Hell Advanced Member

    Joined:
    Jul 12, 2015
    Messages:
    65
    Location:
    Chicagoland area
    Country:
    United States
    Now if only someone could write a guide as detailed as this for NTR cheat plugins or at least make some sort of converter that spits ARcodes/gameshark codetypes to NTR source codes...
     
  8. FF777

    Member FF777 人を呪わば穴二つ

    Joined:
    Nov 22, 2006
    Messages:
    124
    Country:
    United States
    What does code type EXXXXXXX do?.. It says that it was added in the gateway 3.6.2 release..
     
  9. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    Well, creating examples for every operation out there would really be too big for this guide. Any particular ideas you want covered? Decreasing a value is fairly easy.
    Noted, must have missed that. Gonna add it to the guide once I have verified what I think it does.
     
  10. DarkIrata

    Member DarkIrata GBAtemp Regular

    Joined:
    Jun 12, 2015
    Messages:
    296
    Country:
    Germany
    I think things like finding uncommon values and editing them, and even if you say its easy, decreasing. Alone for the decreasing i searched really long..
     
  11. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    This guide has left out how to find addresses on purpose. Explaining these strategies in detail would really require another guide just as long.

    And quite frankly, I don't feel like I am capable of providing any complex strategies myself so I am not qualified to write such a tutorial/guide in the first place. But feel free to write something up, I'll gladly link a tutorial in the OP.
     
    DarkIrata likes this.
  12. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    Added 0xE code type as requested, slightly complex.
     
  13. json

    Member json MUSCLEMAN

    Joined:
    Aug 9, 2013
    Messages:
    673
    Country:
    Bahamas, The
    Localhorst86 likes this.
  14. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    Last edited by Localhorst86, Jan 26, 2016
  15. FF777

    Member FF777 人を呪わば穴二つ

    Joined:
    Nov 22, 2006
    Messages:
    124
    Country:
    United States
    So you know how then?.. I am interested in knowing also.. How do you do it exactly?..
    I don't understand why they didn't just add a code type to decrease a value.. Seems a bit single-minded when they created the code types: "More hearts! More rupees! More magic! No one will ever want to decrease any thing, only increase, muhahaha!"
     
  16. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    As an example, we're going to decrease an 8-bit value, but it will work with 16-bit/32-bt as well.

    DB000000 0123ABCD - Load the value at address 0x123ABCD into the data register (DR). Lets assume it is 0x06.
    D4000000 000000FF - adds 0xFF to our Data register. To understand this, imagine the data register to actually be 32 bit. Our first code set this to 0x00000006. When we add FF, the content of the register will be 0x00000105
    D8000000 0123ABCD -writes the lower 8-bit of our Data Register (0x05) to the address 0x123ABCD
     
  17. FF777

    Member FF777 人を呪わば穴二つ

    Joined:
    Nov 22, 2006
    Messages:
    124
    Country:
    United States
    EDIT: oooooook I guess gbatemp merges your posts together in to 1 post even if they are seperate and completely unrelated posts.. So this post is actually 2 different and unrelated posts that I made..

    POST 1:
    Ohh okay that makes sense.. Not too difficult.. Thanks..

    Now how do you do multiplication and floating-point division?.. (joking)

    — Posts automatically merged - Please don't double post! —

    POST 2:
    So, I want gateway to add an other cheat search option that is really useful and would be extremely simple to add..
    It is the "I forgot" option and I have seen other cheat-searching things use it in the past..
    What is the best way to try to get them to add this option? Email them directly?..

    Explaination of the feature:
    What it does is take a new snapshot (refreshes) of the values in your search list with out resetting the entire search list..
    This is really handy when you have been searching for a value for a long time and then you don't remember what search you ran last time..

    I will give you a good example:
    • You are playing zelda tri-force heroes, trying to find the value for amount of hearts..
    • You know that the game sub-divides each heart in to smaller pieces (but you are not sure how small), and therefore searching for an exact value of "9" when you have 9 hearts will not work, so you can't do exact search, and must instead rely on relative search instead (greater/lesser/equal/different)..
    • Relative search always takes more time than exact search, so you go through a few levels, constantly stopping every once in a while to search again for greater/lesser/etc on your current heart value..
    • When you finish one of the levels, the king unexpectedly starts blabbing on and on about how great of a hero you are and you just really just want him to shut up so you can continue on your way..
    • After he finally shuts up, you go in to an other level and fight some monsters for a minute..
    • You pull up the cheat search menu only to realize "Oh crap, what was my heart value the last time I ran this search?"

    The only thing you can do at this point is either:
    • A: Guess which search option to pick (greater/lesser/etc) and pray really hard that you chose correctly, otherwise you might cull out the value that you have been searching for this whole time..
    • B: Reset your whole search from scratch knowing that all of that time you spent searching is now wasted..

    This is where the "I forgot" option comes in handy; to save your ass when you inevitably forget where the value was the last time you searched..
    What it does is update the values in your search list to their current values, but with out culling any thing and with out resetting the whole search from scratch..
    So if you had spent time culling your possibility list down to say 8 possibilities, and then use "I forgot", you will still have 8 possibilities and can continue searching after that despite that you forgot what the previous value was..

    It doesn't necessarily have to be called "I forgot", but what ever it is called, it is a really handy feature when you are in trouble, and I would like to know the best way to tell gateway to add it..
     
    Last edited by FF777, Jan 26, 2016
  18. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    Emailing them probably has the highest chance of them acknowledging the request. Whether or not they implement that feature is another question, though.
     
  19. FF777

    Member FF777 人を呪わば穴二つ

    Joined:
    Nov 22, 2006
    Messages:
    124
    Country:
    United States
    What is the recommended use for D2000000 (the "end code" instruction)?.. Is it recommended to have it at the end of every code?..
    I am going to go in to a bit of technical detail here.. I tend to write large posts, so sorry in advance..

    From my experience so far it seems that it would be best practice to have the D2 instruction either at the end of every code, or at the beginning of every code, and I will explain why..

    From what I can tell, for some (seemingly stupid) reason, the cheat codes can affect each other.. In other words, if you use D3 (set offset) in one code, that offset will still be in effect when the next code is invoked.. The offset will not be reset unless you use the D2 (end code) instruction..

    In a game I have been playing recently (zelda tri-force heroes) I have created some codes for my self, but found that if I don't end the codes with D2 (end code), the game will freeze if I turn multiple certain codes on at the same time..
    I will give an example:

    [Infinite Fairies]
    D3000000 32DA9D50 (set offset to address 32DA9D50)
    20000000 00000004 (write 8-bit value of 0x4)

    [Infinite Hearts]
    DB000000 32CA6405 (set the (8-bit) data-register to the value stored in address 32CA6405+offset)
    D3000000 32CA6404 (set the offset to address 32CA6404)
    D8000000 00000000 (write an 8-bit value from the data-register (it writes it to 32CA6404))
    D2000000 00000000 (end code, reset offset to zero et cetera)

    The reason the "Infinite Hearts" code does not simply write a value to your current hearts (stored in 32CA6404) is because the sword-suit only let's you use the blade-beam if your current hearts (32CA6404) is exactly equal to your maximum possible hearts (stored in 32CA6405).. So if you simply write a value like 0x48 to address 32CA6404, your current hearts will actually be greater than the maximum number of hearts that you are supposed to be able to hold (32CA6405)..
    Therefore, the code instead copies the maximum number of hearts (32CA6405) in to the data-register, and then sets the offset to address 32CA6404 (your current hearts) and writes to it.. This way your current hearts and maximum hearts will always be equal so that you can use the blade-beam when you have the sword-suit equiped..

    However, a problem was happening at first.. When I turned on only "Infinite Fairies" it worked fine.. And when I turned on only "Infinite Hearts" it worked fine.. But when I turned on both of them, the game would instantly freeze, requiring a hard reset..
    The problem was that the D3 offset instruction placed in "Infinite Fairies" is not reset after the end of that code, and when the "Infinite Hearts" code runs next, it tries to run the DB instruction, and the DB instruction adds which ever address you gave it in the second half of that line (32CA6405) plus any previous offsets (the 32DA9D50 address from the "Infinite Fairies" code).. It tries to add those two addresses together and gets a sum of 65A50155.. Obviously that address is way out of bounds and totally doesn't exist.. And when the DB instruction tries to access that non-existent address, it doesn't just fail silently and move on, it locks-up your whole system.. (Time to improve your error-handling gateway)..

    The solution is simple: Just add a D2 (end code) instruction to the end of "Infinite Fairies" so that the offset gets reset back to 0 in preparation for the next code to be executed.. If I do that, I can turn on both codes simultaneously and the game runs fine..

    My reason for this post is two-fold:
    1: To inform people that it is probably best to end all of the codes that they create with a D2 instruction (or maybe add it manually to any codes that you get from the internet), this way you can avoid any potential lock-ups from multiple codes trying to access an address+offset..
    and 2: I wanted to ask if you guys think this is the best approach or not?.. Is this the recommended way, to add D2 to the end of every single code? And I wanted to ask why we don't see more of the codes on places like fort42 have a D2 instruction at the end..

    While writing this, it also occured to me that the "Infinite Hearts" code could potentially be made to defend its self against other bad codes that did not terminate with a D2 instruction.. If you added an extra instruction to the beginning of "Infinite Hearts" (maybe like "D3000000 00000000") to manually reset the offset before using the DB instruction, I guess that would work too..

    Which do you guys think should be the proper way to make codes? Try to have every one terminate their codes with "D2" instruction? Or to just pre-emptively harden the codes that you make to defend against codes that didn't properly reset them selves using D2?..

    Also, why in god's name didn't gateway just make every code implicitly execute a D2 instruction when it is done, instead of expecting all users to either add D2 manually to every code or to defend against bad codes that didn't use it??.. That just seems like very sloppy programming to not have every thing reset automatically for the next code.. You shouldn't have to worry about other peoples' codes that they made while you are trying to create your own code..
     
    DarkIrata likes this.
  20. Localhorst86
    OP

    Member Localhorst86 GBAtemp Advanced Fan

    Joined:
    Jul 17, 2014
    Messages:
    676
    Country:
    Germany
    You bring up a good point. As I have written in my guide, using an 0xD2 code type at the end of the code is always recommended to clear the data register, offset and terminate any open conditionals or loops. This is what we should try to teach people, preemptively setting 0xD2 would work as well, but it wouldn't solve the problem. People who know that they should use the 0xD2 terminator before beginning a new code can sanitize other people's codes when putting them on their microSD. So you should never have an issue since you know about the code now.

    What's more of an issue is that people who don't know about this and simply use codes from fort42 might run into these issues, not knowing what causes them, and simply have their console freeze. There's nothing we can do to help them other than try to spread the word about using the proper terminator.

    On another note, this is how your infinite heart code would work without your infinite fairy code breaking the offset:

    [Infinite Hearts]
    D3000000 32CA6404 (set the offset Tod address 32CA6404)
    DB000000 00000001 (set the (8-bit) data-register to the value stored in address 0x1+offset)
    D8000000 00000000 (write an 8-bit value from the data-register (it writes it to 32CA6404))
    D2000000 00000000 (end code, reset offset to zero et cetera)

    Getaway doesn't even seem to know about the D2 terminator as they only documented D0 and D1. They probably assumed that only people who knew how to create codes would create them, but the tools are so easy to use that anyone can do it and they didn't help by providing a half-complete documentation.
     

Share This Page