• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Help Thread: ASM & Disassembly

Status
Not open for further replies.
Thank you very much! :)
I'd just need some clarifications: everytime I call a function, I have to load it into rX register, then use "bl *label*" and put "bx rX" in that label? The function is executed after that last line, correct? And does it automatically put the value stored in LR into PC at the end of the function?
About flags, they all can be accessed by 0xXXX then?
Sorry for bothering.

EDIT
I found these lines in a code


In this case, after executing the function it all ends because I haven't stored PC (or LR?) with bl?

ugh, I hate that way of doing it. You have the bx command taking up 2 bytes every time you needed to jump if you do the way which you've quoted. It's not anymore efficient, and not any more readable either, it just wastes space. Only hipsters use it.


Did you read my explanation for how the bl and bx work together to create the longer jump range while allowing the return? The answer to your question was there in that explanation. Anyways,


everytime I call a function, I have to load it into rX register, then use "bl *label*" and put "bx rX" in that label?
Yeah that's the best way when you can't just use a bl.

The function is executed after that last line, correct? And does it automatically put the value stored in LR into PC at the end of the function?
I don't understand the question, but basically LR = PC when bl is used. So actually when the called function returns via pop pc or bx lr or something, then you go to the line after that "bl".
 
I don't understand the question, but basically LR = PC when bl is used. So actually when the called function returns via pop pc or bx lr or something, then you go to the line after that "bl".

LR = PC + 4.

Thank you very much! :)
I'd just need some clarifications: everytime I call a function, I have to load it into rX register, then use "bl *label*" and put "bx rX" in that label? The function is executed after that last line, correct? And does it automatically put the value stored in LR into PC at the end of the function?

It doesn't automatically do it. You have to do it. If you do BX LR, that sets PC = LR. pop {..., pc} also can return, assuming you've done a corresponding push {..., lr}. That uses the stack to transfer the value of LR to PC. There are a number of ways of doing it. See my tutorial for a more thorough explanation on this.

About flags, they all can be accessed by 0xXXX then?
Sorry for bothering.

If you call that checkflag function, then yes. It's basically exactly the same as the script function except it can be called from ASM code.

EDIT
I found these lines in a code

In this case, after executing the function it all ends because I haven't stored PC (or LR?) with bl?

Not quite sure what you mean by "it all ends". This does exit the routine because it is branching away, but execution of engine code still continues.
This is part of what we call a hook. It is a way of modifying an existing routine without being encumbered by space limitations. Basically we find a function and hijack execution so that the function branches to free space. We then use a special routine that performs the action we want and branch back. The part you linked looks like the part that branches back to the original function.
 
Allright, thanks to you both! The first time I read your tutorials there were many things I couldn't understand but now I think they're clear.
So then, if I use bl+bx, that's what happens: bl allows me to return to the next instruction of my code (after executing the function), while bx just branches to the function.
If I use bl only, the function should not be "too far" or it may not work.
If I use bx only, it exits my routine, executes the function, then keeps on executing the code just after the function (not the one I wrote I mean).
In short, bl sets LR = PC + 4 but hasn't got unlimited range while bx has unlimited range but it doesn't set LR?
 
I have here this routine for cmda6 which locks up the game when it runs. Yes, I've incremented the offset by 1. And yes, it's at an aligned location.
Code:
.text
.align 2
.thumb
.global walkingscript

main:
push {r4,r5,lr}
add sp, #-0x4
lsl r0, r0, #0x18 @ getQueueItemByIndex
lsr r0, r0, #0x18
lsl r1, r0, #0x2
add r1, r1, r0
lsl r1, r1, #0x3
ldr r0, exec_queue
add r5, r1, r0 @ /getQueueItemByIndex
mov r4, sp
add r4, #0x2
mov r0, sp
add r1, r4, #0x0
ldr r2, get_player_coords
bl linker @ Store player coordinates at [r0] and [r1], respectively.
mov r0, sp @ Start checking if player coordinates have changed.
ldrh r2, [r0, #0x0]
mov r3, #0x0
ldsh r1, [r0, r3]
mov r3, #0x2
ldsh r0, [r5, r3]
cmp r1, r0
bne process
mov r0, #0x0
ldsh r1, [r4, r0]
mov r3, #0x4
ldsh r0, [r5, r3]
cmp r1, r0
beq return @ Fall through to process

process:
strh r2, [r5, #0x2]
ldrh r0, [r4, #0x0]
strh r0, [r5, #0x4]
mov r0, sp
mov r1, #0x0
ldsh r0, [r0, r1]
mov r2, #0x0
ldsh r1, [r4, r2]
ldr r2, get_background_byte
bl linker @ r0: BG byte of tile the player's standing on; r4: sp + 2, pointer
lsl r0, r0, #0x18
lsr r0, r0, #0x18
@ Skip bl to return; that's what cripples the routine
lsl r0, r0, #0x18
cmp r0, #0x0
beq return @ Return if no background byte
mov r0, sp
mov r3, #0x0
ldsh r0, [r0, r3] @ r0 = player x
mov r2, #0x0
ldsh r1, [r4, r2] @ r1 = player y
ldr r2, get_tile_number
bl linker @ r0 = tile number the player's on
@ REGISTERS: see note 1
ldr r1, tile_table
mov r2, #0x0
ldr r4, table_delimiter
ldrh r4, [r4, #0x0]

loop:
ldrh r3, [r1, r2] @ Load the current value
cmp r3, r4 @ Compare the current value to our delimiter.
beq return @ And return if we finished reading the table.
cmp r3, r0 @ Compare the current value to the tile number the player's on.
bne next_entry @ Read the next entry if the two aren't equal.
ldr r0, script
ldr r2, script_executor
bl linker

return:
add sp, #0x4
pop {r4, r5}
pop {r0}
bx r0

next_entry:
add r2, r2, #0x2 @ Increase our table offset by 0x2.
b loop @ Read the next entry.

linker:
bx r2

.align 2
exec_queue: .word 0x03005098
get_player_coords: .word 0x0805C538
get_background_byte: .word 0x08058F78
get_tile_number: .word 0x08058E48
script_executor: .word 0x08069AE4
table_delimiter: .word 0x0000
tile_table: .word 0x08AAAAAA
script: .word 0x8BBBBBB

@ Tile number table: [TILE NUMBER - 2 bytes] [END - 0000]
@ note 1:
@  - r0: tile number
@  - r1: table location
@  - r2: table offset
@  - r3: table value
@  - r4: delimiter
 
I have here this routine for cmda6 which locks up the game when it runs. Yes, I've incremented the offset by 1. And yes, it's at an aligned location.
Code:
.text
.align 2
.thumb
.global walkingscript

main:
push {r4,r5,lr}
add sp, #-0x4
lsl r0, r0, #0x18 @ getQueueItemByIndex
lsr r0, r0, #0x18
lsl r1, r0, #0x2
add r1, r1, r0
lsl r1, r1, #0x3
ldr r0, exec_queue
add r5, r1, r0 @ /getQueueItemByIndex
mov r4, sp
add r4, #0x2
mov r0, sp
add r1, r4, #0x0
ldr r2, get_player_coords
bl linker @ Store player coordinates at [r0] and [r1], respectively.
mov r0, sp @ Start checking if player coordinates have changed.
ldrh r2, [r0, #0x0]
mov r3, #0x0
ldsh r1, [r0, r3]
mov r3, #0x2
ldsh r0, [r5, r3]
cmp r1, r0
bne process
mov r0, #0x0
ldsh r1, [r4, r0]
mov r3, #0x4
ldsh r0, [r5, r3]
cmp r1, r0
beq return @ Fall through to process

process:
strh r2, [r5, #0x2]
ldrh r0, [r4, #0x0]
strh r0, [r5, #0x4]
mov r0, sp
mov r1, #0x0
ldsh r0, [r0, r1]
mov r2, #0x0
ldsh r1, [r4, r2]
ldr r2, get_background_byte
bl linker @ r0: BG byte of tile the player's standing on; r4: sp + 2, pointer
lsl r0, r0, #0x18
lsr r0, r0, #0x18
@ Skip bl to return; that's what cripples the routine
lsl r0, r0, #0x18
cmp r0, #0x0
beq return @ Return if no background byte
mov r0, sp
mov r3, #0x0
ldsh r0, [r0, r3] @ r0 = player x
mov r2, #0x0
ldsh r1, [r4, r2] @ r1 = player y
ldr r2, get_tile_number
bl linker @ r0 = tile number the player's on
@ REGISTERS: see note 1
ldr r1, tile_table
mov r2, #0x0
ldr r4, table_delimiter
ldrh r4, [r4, #0x0]

loop:
ldrh r3, [r1, r2] @ Load the current value
cmp r3, r4 @ Compare the current value to our delimiter.
beq return @ And return if we finished reading the table.
cmp r3, r0 @ Compare the current value to the tile number the player's on.
bne next_entry @ Read the next entry if the two aren't equal.
ldr r0, script
ldr r2, script_executor
bl linker

return:
add sp, #0x4
pop {r4, r5}
pop {r0}
bx r0

next_entry:
add r2, r2, #0x2 @ Increase our table offset by 0x2.
b loop @ Read the next entry.

linker:
bx r2

.align 2
exec_queue: .word 0x03005098
get_player_coords: .word 0x0805C538
get_background_byte: .word 0x08058F78
get_tile_number: .word 0x08058E48
script_executor: .word 0x08069AE4
table_delimiter: .word 0x0000
tile_table: .word 0x08AAAAAA
script: .word 0x8BBBBBB

@ Tile number table: [TILE NUMBER - 2 bytes] [END - 0000]
@ note 1:
@  - r0: tile number
@  - r1: table location
@  - r2: table offset
@  - r3: table value
@  - r4: delimiter

It would be nice if you could tell us what this routine is supposed to be doing, that way I don't have to decipher.
Immediately, the first issue I see are these function pointers:

Code:
get_player_coords: .word 0x0805C538
get_background_byte: .word 0x08058F78
get_tile_number: .word 0x08058E48
script_executor: .word 0x08069AE4

You need to add +1 to the addresses listed here (obviously you don't need to for the table/script ones). There are a few efficiency issues here and there, but nothing which would impact the routine to cause a freeze/crash. I suggest adding +1 to those, and then stepping through a debugger if the issue persists.
 
It would be nice if you could tell us what this routine is supposed to be doing, that way I don't have to decipher.
Immediately, the first issue I see are these function pointers:

Code:
get_player_coords: .word 0x0805C538
get_background_byte: .word 0x08058F78
get_tile_number: .word 0x08058E48
script_executor: .word 0x08069AE4
You need to add +1 to the addresses listed here (obviously you don't need to for the table/script ones). There are a few efficiency issues here and there, but nothing which would impact the routine to cause a freeze/crash. I suggest adding +1 to those, and then stepping through a debugger if the issue persists.
First of all, I'm a total idiot for those pointers. I'll just check them out and see if that works. As for efficiency, this is practically a carbon copy of one of the routines from the original game. The purpose is basically to check if you've moved since last frame and execute a script if you have and are standing on a tile, the number of which is present in a table.
Edit: That totally worked and made me feel super dumb, especially considering I mentioned adding +1 in my original post. Now to figure out why searching through a 6-byte table takes 10 seconds, literally.
 
Last edited:
First of all, I'm a total idiot for those pointers. I'll just check them out and see if that works. As for efficiency, this is practically a carbon copy of one of the routines from the original game. The purpose is basically to check if you've moved since last frame and execute a script if you have and are standing on a tile, the number of which is present in a table.
Edit: That totally worked and made me feel super dumb, especially considering I mentioned adding +1 in my original post. Now to figure out why searching through a 6-byte table takes 10 seconds, literally.

Oh, I see. This is not the way you should go about doing this. Make a hook for something that gets executed on a per step basis (increasing execution efficiency), either that or just make a task.
 
GBATEK reports these informations:
General Internal Memory
00000000-00003FFF BIOS - System ROM (16 KBytes)
00004000-01FFFFFF Not used
02000000-0203FFFF WRAM - On-board Work RAM (256 KBytes) 2 Wait
02040000-02FFFFFF Not used
03000000-03007FFF WRAM - On-chip Work RAM (32 KBytes)
03008000-03FFFFFF Not used
04000000-040003FE I/O Registers
04000400-04FFFFFF Not used
Internal Display Memory
05000000-050003FF BG/OBJ Palette RAM (1 Kbyte)
05000400-05FFFFFF Not used
06000000-06017FFF VRAM - Video RAM (96 KBytes)
06018000-06FFFFFF Not used
07000000-070003FF OAM - OBJ Attributes (1 Kbyte)
07000400-07FFFFFF Not used
External Memory (Game Pak)
08000000-09FFFFFF Game Pak ROM/FlashROM (max 32MB) - Wait State 0
0A000000-0BFFFFFF Game Pak ROM/FlashROM (max 32MB) - Wait State 1
0C000000-0DFFFFFF Game Pak ROM/FlashROM (max 32MB) - Wait State 2
0E000000-0E00FFFF Game Pak SRAM (max 64 KBytes) - 8bit Bus width
0E010000-0FFFFFFF Not used
Unused Memory Area
10000000-FFFFFFFF Not used (upper 4bits of address bus unused)

However, when I use an hex editor (such as HxD), which part of memory does it display?
The ROM usually is 16 MB and all that memory is just contained in 08000000-08FFFFFF?
If so, how can I hack Palette/Images or RAM?
 
GBATEK reports these informations:
-snip-
However, when I use an hex editor (such as HxD), which part of memory does it display?
The ROM usually is 16 MB and all that memory is just contained in 08000000-08FFFFFF?
If so, how can I hack Palette/Images or RAM?
The hex editor displays the 08000000-08FFFFFF and (if the game is 32 MB) the 09000000-09FFFFFF ranges (that is, the contents of the ROM - read only memory. It's called that because you can't change it at run time). The palettes and the images are contained in that memory and just get copied to the VRAM or wherever else during run time, so it's a matter of finding them in the hex editor and changing them. The RAM is well, random access memory. It gets wiped out when you turn off the emulator (actually, your PC has RAM too if you didn't know) because it's not persistent memory. RAM can only be "hacked" using ASM, or for that matter, cheat codes.
 
The hex editor displays the 08000000-08FFFFFF and (if the game is 32 MB) the 09000000-09FFFFFF ranges (that is, the contents of the ROM - read only memory. It's called that because you can't change it at run time). The palettes and the images are contained in that memory and just get copied to the VRAM or wherever else during run time, so it's a matter of finding them in the hex editor and changing them. The RAM is well, random access memory. It gets wiped out when you turn off the emulator (actually, your PC has RAM too if you didn't know) because it's not persistent memory. RAM can only be "hacked" using ASM, or for that matter, cheat codes.
Thank you very much! The image/palette's offset is just the one Unlz displays, right?
And in this case, what will I find in the hex editor at the image's offset? How are those hexadecimals linked to the image?
 
so i have this code made by touched in THIS thread
Code:
.text
.align 2
.thumb
.thumb_func

main:
    push {lr}

    ldr r0, =(0x02024284)
    mov r1, #0x27
    mov r2, #0x1F
    push {r2}
    mov r2, sp
    ldr r3, =(0x0804037C + 1)
    bl call_via_r3
    pop {r2}
    pop {pc}

call_via_r3:
    bx r3

this code changes the HP IV of a pokemon, however it only does it to the first pokemon in the player's party, how would i modify it for use in a givepokemon script so the given pokemon has the changed HP IV?
 
Last edited:
so i have this code made by touched in THIS thread
Code:
.text
.align 2
.thumb
.thumb_func

main:
    push {lr}

    ldr r0, =(0x02024284)
    mov r1, #0x27
    mov r2, #0x1F
    push {r2}
    mov r2, sp
    ldr r3, =(0x0804037C + 1)
    bl call_via_r3
    pop {r2}
    pop {pc}

call_via_r3:
    bx r3

this code changes the HP IV of a pokemon, however it only does it to the first pokemon in the player's party, how would i modify it for use in a givepokemon script so the given pokemon has the changed HP IV?
You should use a hook for givepokemon. This is designed for cases where the Pokemon is in your party. If you did givepokemon, it's possible the Pokemon would just go straight to the PC. So this part here:

Code:
ldr r0, =(0x02024284)
Which is the address of the first Pokemon on your party, would be needing changes (but if it's sent to the PC, you can't do the traditional way of countpokemon * 64 + address).

So to reiterate, you should place a hook at the createpokemon routine, and there you can make a routine that works like this, but with your own switch (var or flag) so it would only happen when you wanted it to happen.

If the Pokemon is 100% going to be in the Player's party (first Pokemon or something), you can use the routine you've quoted and just adjust

Code:
ldr r0, =(0x02024284)

like I've stated earlier in the post~
 
Hello, I'm trying to make a routine that adds a value on a certain stat but I couldn't make it work, it doesn't freeze the game but it doesn nothing, I know it has errors but I don't know what to edit, here's what I made.
Spoiler:
 
many stuffs

that's simpler than i thought, thank you

okay, so i should make 5 routines (one for each extra slot), and change
Code:
ldr r0, =(0x02024284)
accordingly , then use countpokemon in xse to work out which of the 5 routines it needs to use, is that right?

also on a side note, this part here
Code:
mov r2, #0x1F
how would i make the value bigger than 0xFF, for things like trainer ID and nickname etc. i do not know the ways of the asm
 
Hello, I'm trying to make a routine that adds a value on a certain stat but I couldn't make it work, it doesn't freeze the game but it doesn nothing, I know it has errors but I don't know what to edit, here's what I made.
Spoiler:

What? I don't understand what the distinction between var 0x8004 and 0x8005 are in your routine. For current HP, the routine is simply:

Code:
	ldr r0, location_of_stat_for_first_pokemon
	ldr r1, =(0x20370B8)
	ldrh r1, [r1]
	mov r2, #0x64
	mul r1, r1, r2
	add r0, r0, r1 @addr of the stat

	ldr r1, =(0x20370C0)
	ldrh r1, [r1]
	strh r1, [r0]
 
that's simpler than i thought, thank you

okay, so i should make 5 routines (one for each extra slot), and change
Code:
ldr r0, =(0x02024284)
accordingly , then use countpokemon in xse to work out which of the 5 routines it needs to use, is that right?

No, you should just use some math. Recall, countpokemon stores the amount of Pokemon in the lastresult (I forget if it's 0-5 or 1-6). From there, you just add to 0x2024284, 0x64 * amount of Pokemon. Lastresult is 0x20370D0 btw.

also on a side note, this part here
Code:
mov r2, #0x1F
how would i make the value bigger than 0xFF, for things like trainer ID and nickname etc. i do not know the ways of the asm

You can't using mov. What you can do is use ldr instead of move for things that are 32 bits (so a nickname won't fit). But set_attr (the function Touched calls in that routine) takes a pointer to the value to set, rather than an actual value (so you don't need to make r2 something other than a pointer. Touched uses the stack, which is probably what confused you. You could use a ROM address. Like this:

Code:
    ldr r0, =(0x02024284)
    mov r1, #0x2
   ldr r2, =(address to nick name)
    ldr r3, =(0x0804037C + 1)
    bl linker
 
What? I don't understand what the distinction between var 0x8004 and 0x8005 are in your routine. For current HP, the routine is simply:

Code:
	ldr r0, location_of_stat_for_first_pokemon
	ldr r1, =(0x20370B8)
	ldrh r1, [r1]
	mov r2, #0x64
	mul r1, r1, r2
	add r0, r0, r1 @addr of the stat

	ldr r1, =(0x20370C0)
	ldrh r1, [r1]
	strh r1, [r0]

Var 8004 dictates the slot number of a pokemon in your party, var 8005 dictates what Stat to modify, 0 being the current HP, 1 being the Total HP, 2 being the ATK , 3 being the DEF and so on, while var 8006 dictates what value to add, that's what I'm trying to do. Sorry for my mistakes hehe I'm so new in ASM, all I can do is compile and insert it.
 
Var 8004 dictates the slot number of a pokemon in your party, var 8005 dictates what Stat to modify, 0 being the current HP, 1 being the Total HP, 2 being the ATK , 3 being the DEF and so on, while var 8006 dictates what value to add, that's what I'm trying to do. Sorry for my mistakes hehe I'm so new in ASM, all I can do is compile and insert it.

That's fine, do you know how to modify the routine I posted to incorporate var 0x8005?
 
Var 8004 dictates the slot number of a pokemon in your party, var 8005 dictates what Stat to modify, 0 being the current HP, 1 being the Total HP, 2 being the ATK , 3 being the DEF and so on, while var 8006 dictates what value to add, that's what I'm trying to do. Sorry for my mistakes hehe I'm so new in ASM, all I can do is compile and insert it.
Stats don't work that way. The only stats outside of the encrypted data section are within the 20 bytes specific only to pokemon in parties. They are calculated based the species' base stat, iv, ev, nature, etc. You cannot simply write a change to them because that change is reversed anytime the stat needs to be recalculated.
 
That's fine, do you know how to modify the routine I posted to incorporate var 0x8005?

Actually I have an idea, I'll try to insert var 8005 there, and if I really give up, I willask for a help. Thanks for the response

Stats don't work that way. The only stats outside of the encrypted data section are within the 20 bytes specific only to pokemon in parties. They are calculated based the species' base stat, iv, ev, nature, etc. You cannot simply write a change to them because that change is reversed anytime the stat needs to be recalculated.

I don't get it. I can manually edit the stats of a pokemon in VBA
 
Status
Not open for further replies.
Back
Top