ROM Hack Cheats: copy pointer value to pointer?

subworx

Member
OP
Newcomer
Joined
Sep 12, 2019
Messages
7
Trophies
0
XP
160
Country
Germany
Hi,

I'm stumped and please need some help.

tl;dr: how do i copy the contents of 0x006E8422 to 0x1485B4D8 (2 bytes, both possibly pointers)?


Looking to copy values from a pointer (max HP) to another pointer (current HP) so I have an "Infinite HP" cheat without setting HP to some arbitrary high value.
Even with the help of (link to nanquitas' github gist "CTRPF Action Replay Code Types") and (link to Codejunkies Datel Trainer Toolkit for DS Manual), I cannot figure out how to accomplish this or which operation(s) actually equals "read". Call me stupid if you want :P

Say current HP is at 0x31234567, pointer, 1 byte.
Max HP is at 0x3123dcb0, pointer, 1 byte.

First I need to set the base offset to 0x30000000 to accomodate the offset length: (D3000000 = set offset #1)
D3000000 30000000
Make sure the pointer is not zero (6xxxxxxx = Not equal, xxxxxxx = pointer address without leading 3 due to offset, compare value is 0):
61234567 00000000
Load actual pointer (Bxxxxxxx = load offset register, value is always 00000000)
B1234567 00000000

Now normally would come the write command (write to current address) with some specific value and that's it.
But how would I go about reading the contents of 0x3123dcb0 and write that value to 0x31234567 instead?

Before of course closing the If opened above with
D2000000 000000

Hope it was not too confusing and someone here knows the answer :)

Also, if both values are simple values instead of pointers, what would the code for this be?

Thanks and regards,
sub

Edit: Further search brought me to codedonut / ds action replay tutorial. The copy there is done with D3 (which I understand to be load first offset) and "0F" (can't find that in nanquitas' reference) instruction. The code used in that example would mean it multiplies something (F2xxxxxx where the 2 would be the offset starting number instead of the operation F2.....?).
Code:
We need to set the offset value to our total crystals address, which means we will use the D3 code type.
This will set the total crystals address as the internal “pointer” register.
D3000000 XXXXXXXX , XX being the address.
Next, we will need to copy memory (bytes), using the 0F code type, which works in conjunction with
the code types (D3, DC or B) to set the offset beforehand. Doing this will copy the bytes specified, from
the internal pointer register (0A3010 or the first line) to our current crystals address (0A3012).
FXXXXXXX YYYYYYYY , XX being the address (current crystals), and YY being the number of bytes
to copy. We’ll do only 1 byte, so 00000001.
D3000000 020A3010
F20A3012 00000001
D2000000 00000000
But how do I go about it if my target offset isn't (0)20A3012 but 120A3012? Prepending an F for the operation makes it 9 characters and thus too long (F120A3012)
This gets weirder and weirder for me :(
 
Last edited by subworx,

subworx

Member
OP
Newcomer
Joined
Sep 12, 2019
Messages
7
Trophies
0
XP
160
Country
Germany
Wow, solved with gbatemp.net/threads/guide-how-to-create-gateway-cheat-codes.410926/, a really really good guide to how to do stuff.

Mario & Luigi: Dream Team (US)
Code:
[Infinite Battle HP/BP]
506D25C8 00000001 - if 0x006d25c8 equals 1, do - 0x006D25C8 = in battle 1/0
DA000000 1485B4D6 - read value from 0x1485B4D6 into buffer = Mario Max HP
D7000000 1485B4D8 - write value from buffer to 0x1485B4D8 = Mario Current HP
D3000000 00000000 - reset offset - write increases offset, get rid of this
DA000000 1485B4DA - read Mario Max BP
D7000000 1485B4DC - write Mario Current BP
D3000000 00000000 - reset offset
DA000000 1485C0A2 - read Luigi Max HP
D7000000 1485C0A4 - write Luigi Current HP
D3000000 00000000 - reset offset
DA000000 1485C0A6 - read Luigi Max BP
D7000000 1485C0A8 - write Luigi Current BP
D2000000 00000000 - end code, close all ifs, reset all buffers
 
  • Like
Reactions: cearp

FAST6191

Techromancer
Editorial Team
Joined
Nov 21, 2005
Messages
33,867
Trophies
2
Website
trastindustries.com
XP
22,600
Country
United Kingdom
Hmm that is quite the gap in memory location between characters. Wonder what is in the middle of it. Also somewhat surprising that the health is only a 16 bit variable but I suppose they don't need much more and it has its perks.

That is also some confusing terminology there with regards to the word pointer. Most times I hear pointer I expect the game is using pointers to store the final location of data, such that the location might vary between boots or levels or something*, where that is a fixed location. Technically (what I am told is the best kind of correct) the quoted section makes sense though.

*you would then be wanting to read the game's own pointer for max HP, use that as the basis for grabbing the data, and presumably then fetching the game's own pointer for current HP to find where the current HP is sitting and go from there (though if it is just 2 bytes onwards** from the max HP you could probably actually use the offset value)

**some games do it like this where individual characters have tables of all their various stats. Others will want to collect all of the same stat together and repeat that with individual tables for the stats. Other games still will do other almost arbitrary things (basically be XML or similar defined rather than have a list of effects/effect strength several kilobytes long for randomly generated weapons/items/characters with most of it being 0) but we are usually spared that one in handheld hacking, though I see the Switch has Borderlands and Skyrim so eh.

Congrats on getting it working though. Quite a few before you have thrown up their hands when running into a block like that.
 
  • Like
Reactions: subworx

subworx

Member
OP
Newcomer
Joined
Sep 12, 2019
Messages
7
Trophies
0
XP
160
Country
Germany
Hmm that is quite the gap in memory location between characters. Wonder what is in the middle of it. Also somewhat surprising that the health is only a 16 bit variable but I suppose they don't need much more and it has its perks.

Yeah, it's weird. Just like me :D
And it came with lots of realizations.

Thanks to the link in the second post, I found the data is stored in one place for the overworld (0x006...) and does not change there except when using items or changing gear. When starting a battle, the whole character data is copied to the second place (0x14...) where all the magic happens.

That is also some confusing terminology there with regards to the word pointer. Most times I hear pointer I expect the game is using pointers to store the final location of data, such that the location might vary between boots or levels or something*, where that is a fixed location. Technically (what I am told is the best kind of correct) the quoted section makes sense though.

*you would then be wanting to read the game's own pointer for max HP, use that as the basis for grabbing the data, and presumably then fetching the game's own pointer for current HP to find where the current HP is sitting and go from there (though if it is just 2 bytes onwards** from the max HP you could probably actually use the offset value)

**some games do it like this where individual characters have tables of all their various stats. Others will want to collect all of the same stat together and repeat that with individual tables for the stats. Other games still will do other almost arbitrary things (basically be XML or similar defined rather than have a list of effects/effect strength several kilobytes long for randomly generated weapons/items/characters with most of it being 0) but we are usually spared that one in handheld hacking, though I see the Switch has Borderlands and Skyrim so eh.

Yeah after digging around, I realized no pointers are involved but the locations are hardcoded. Shame on me.
If they were pointers, I think using Bxxxxxxxx 00000000 would have returned the proper "real" addresses to copy from and to, so that most likely would not have been that much of a problem.

The main gripe was, I was too stupid at first to understand which commands actually "copy from address to buffer" and "write from buffer to address".

Then I also realized that luckily I don't have to copy the value from the 0x006... address to the 0x14... address but can stay in the 14... range as the values are all right there - and even the correct ones!
Why correct? It's about Mario & Luigi: Dream Team. When entering battles in the dream world, HP and BP are increased and do not match Mario's or Luigi's base values any more. This happens in the 0x14.... range only, the change does not show in the 0x006.. range during battle, this gets updated afterwards.

Congrats on getting it working though. Quite a few before you have thrown up their hands when running into a block like that.

Thank you very much :)
Sometimes the game crashes and I cannot find the exact reason (the first If should filter out battle/non-battle mode)... oh well *shrug*. Save early, save often :P
 
General chit-chat
Help Users
  • No one is chatting at the moment.
    The Real Jdbye @ The Real Jdbye: 🍆 +3