• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • 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.

daniilS

busy trying to do stuff not done yet
  • 409
    Posts
    10
    Years
    • Seen Jan 29, 2024
    You forgot the +1. And again, this is not how everyone advices you to do it.
     
  • 40
    Posts
    10
    Years
    Wait, you're trying to test Psystrike's battle effect in the OW with a signpost script? Really?

    This should be put in a battlescript which is then attached to an attack. Then used in a battle. Wow.

    I know, it is to test the swap. It will work in a script and in a battle script, no ?


    So it is "callasm 0xOffset +1", thank you.
     

    GoGoJJTech

    (☞゚ヮ゚)☞ http://GoGoJJTech.com ☜(゚ヮ゚☜)
  • 2,475
    Posts
    11
    Years
    I know, it is to test the swap. It will work in a script and in a battle script, no ?


    So it is "callasm 0xOffset +1", thank you.

    You don't seem to understand..
    It's a code for a move. There is no battle scene on the overworld. You can't just "callasm 0xmovescript" and make psystrike happen on the overworld. It doesn't make sense lol
     
  • 40
    Posts
    10
    Years
    You don't seem to understand..
    It's a code for a move. There is no battle scene on the overworld. You can't just "callasm 0xmovescript" and make psystrike happen on the overworld. It doesn't make sense lol

    This routine is not the move's script. It just swaps two "double bytes". I can swap two bytes when I want, in battle or not.
    It will be call in the psystrike's battlescript.

    But I have another question ! How to port the Jambo's callasm command ? I compile the routine with the address 0x02024214 for the scriptlocation (because I am on Emerald). Ok, but I have to repoint and extend the battle script command table to had the new command F9 XX XX XX 08. Where is this table ? And how do you find it ?
     
  • 40
    Posts
    10
    Years
    Do you have battle script pro?
    You can use that to compile battle scripts.
    Yes of course, i know how to create a battlescript.
    I want to insert an ASM routine in my battlescript using Jambo's callasm command. I'm on Emerald so i have to use the address 0x02024214 as scriptlocation. But I also have to repoint and extend the battle script command table. I don't find it.

    Edit : I found it! The table is at 0x31BD10 and its length is 0x3E4.
     
    Last edited:

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    I would like to know, if it's possible, the offset of two routines :

    - First, the one which creates an OW on the map when we come on this map ;
    - And also, the one which check if there is an OW next to the player before walking.

    Can someone help me ? Thanks ^^

    Hi, unfortunately I don't know where the overworld is created. Though I do know that there's a collision check which occurs when the player tries to use surf or waterfall.

    This sub routine is at 0x805C8B0. More specifically, the check to see if an NPC is blocking the way is done at 0x80636AC, it's used for stuff like ledge hopping and stuff too.
     
  • 40
    Posts
    10
    Years
    Hello,

    I don't understand why this doesn't work :
    Spoiler:


    Whereas this works :
    Spoiler:


    With the first routine I want to switch some bytes and with the second i switch some "double bytes".
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Hello,

    I don't understand why this doesn't work :
    Spoiler:


    Whereas this works :
    Spoiler:


    With the first routine I want to switch some bytes and with the second i switch some "double bytes".

    Hi, it looks like it would do the same. I don't know which base you're using, but the offsets of the symbols from routine #1 don't match the offsets of the symbols in routine #2. Other than that, swapping a byte instead of a half word shouldn't be a problem (actually the halfword one has more limitations than the byte swapping, but that's besides the point).
     
  • 40
    Posts
    10
    Years
    Hi, it looks like it would do the same. I don't know which base you're using, but the offsets of the symbols from routine #1 don't match the offsets of the symbols in routine #2. Other than that, swapping a byte instead of a half word shouldn't be a problem (actually the halfword one has more limitations than the byte swapping, but that's besides the point).

    The first one is to swap stat changes, and the second one is to swap stats. So it is normal that the offsets are not the same. Yes it shouldn't be a problem, that's why i don't understand why the game resets with the first routine.

    Edit: Well, i'm stupid, I forgot a "0":
    .CDEFA2:
    .word 0x202414E

    .CDEFA2:
    .word 0x0202414E
     
    Last edited:
  • 88
    Posts
    13
    Years
    • Seen Jun 18, 2020
    Hi, unfortunately I don't know where the overworld is created. Though I do know that there's a collision check which occurs when the player tries to use surf or waterfall.

    This sub routine is at 0x805C8B0. More specifically, the check to see if an NPC is blocking the way is done at 0x80636AC, it's used for stuff like ledge hopping and stuff too.

    Thanks a lot ;)

    I found something : the result given by the routine at 0x80636AC is stored in r0.

    Code:
    [U][B]Value of r0[/B][/U]	|	[U][B]Obstacle[/B][/U]
    0 		|	Nothing
    2 		|	Solid block (buildings, trees...)
    3 		|	Walking : water / Surfing : ground
    4 		|	NPC
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Thanks a lot ;)

    I found something : the result given by the routine at 0x80636AC is stored in r0.

    Code:
    [U][B]Value of r0[/B][/U]	|	[U][B]Obstacle[/B][/U]
    0 		|	Nothing
    2 		|	Solid block (buildings, trees...)
    3 		|	Walking : water / Surfing : ground
    4 		|	NPC

    Awesome. Did you figure out if it takes a player's X-Y? If it does perhaps it can be used to check if something is present on another part of the map the player isn't in currently.
     
  • 88
    Posts
    13
    Years
    • Seen Jun 18, 2020
    I haven't studied the routine more, I used this data to make a Follow Me (https://vid.me/ynwf / https://vid.me/hSBA).

    However, I noticed that before the execution of this routine, r1, r5 and r7 correspond to the player's X + 7. In the same way, r2, r4 and r9 correspond to the player's Y + 7.
     
  • 10,078
    Posts
    15
    Years
    • UK
    • Seen Oct 17, 2023
    NOOB HERE! o/

    If this (from Shiny Quagsire's tutorial) saves a byte to a variable...

    Spoiler:


    Then would switching "ldr r0, pokemon_data" to "ldr r0, var" (ldr r1, var too) then store whatever the value of 0x800D in the data? Or is life not that simple : <.
     
    Last edited:

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    NOOB HERE! o/

    If this (from Shiny Quagsire's tutorial) saves a byte to a variable...

    Spoiler:


    Then would switching "ldr r0, pokemon_data" to "ldr r0, var" (ldr r1, var too) then store whatever the value of 0x800D in the data? Or is life not that simple : <.

    You'll notice that he saves the value in r0 into the address in r1 (the variable).
    So all you need to do is this:

    Code:
    push {r0-r1, lr}
    mov r0, #0xValue
    ldr r1, .var
    strh r0, [r1]
    pop {r0-r1, pc}
     
  • 10,078
    Posts
    15
    Years
    • UK
    • Seen Oct 17, 2023
    You'll notice that he saves the value in r0 into the address in r1 (the variable).
    So all you need to do is this:

    Code:
    push {r0-r1, lr}
    mov r0, #0xValue @changes r0 to 0xValue?
    ldr r1, .var @loads variable value to r1
    strh r0, [r1] @stores r0's value to the var
    pop {r0-r1, pc}

    All this lingo still confuses me XD.

    Sorry I'm not sure what you mean :<. Your code doesn't have any locations other than the var, so how can it set a byte to the value of the var? It might have just been I wasn't clear in my last post >< haha.

    Also in regards to your tutorial (and our VMs) how do you know when you need to 'hook' and things?


    Latest attempt of a routine. Think I must have oversimplified something? I get nothing ><. It runs but obviously not doing what I'd like it to XD. Vague comments about what I think ought to be happenin on the side :').

    Spoiler:

    It now tells me 55 - which is correct! :o 50+5 power. How can I then extend this routine to replace the 50 (0x32) in the ROM with 55 (0x37)?

    IM SO SORRY FOR ALL THE NOTIFICATIONS ;-; /thousanth edit
     
    Last edited:

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Code:
    push {r0-r1, lr}
    mov r0, #0xValue @changes r0 to 0xValue?
    ldr r1, .var @loads variable value to r1
    strh r0, [r1] @stores r0's value to the var
    pop {r0-r1, pc}

    All this lingo still confuses me XD.

    Sorry I'm not sure what you mean :<. Your code doesn't have any locations other than the var, so how can it set a byte to the value of the var? It might have just been I wasn't clear in my last post >< haha.

    Also in regards to your tutorial (and our VMs) how do you know when you need to 'hook' and things?


    Latest attempt of a routine. Think I must have oversimplified something? I get nothing ><. It runs but obviously not doing what I'd like it to XD. Vague comments about what I think ought to be happenin on the side :').

    Spoiler:

    It now tells me 55 - which is correct! :o 50+5 power. How can I then extend this routine to replace the 50 (0x32) in the ROM with 55 (0x37)?

    IM SO SORRY FOR ALL THE NOTIFICATIONS ;-; /thousanth edit

    OK, so when you do "ldr r0, move_data" you don't load it as a byte. move_data is a symbol which represents a pointer (in this case 0x8250CB8 + 1). We want a byte at that pointer so we do:
    ldr r0, move_data @load the actual pointer
    ldrb r0, [r0] @load a byte from the value of the pointer

    If you did ldrb r0, move_data, it would just take move_data as a hex value and load the first byte of it, rather than the first byte of the value it's pointing to (power).

    The rest of this is right. Also you seem to be confusing yourself with the names on the bottom. They're just definitions. It's the same thing to do ldr r0, move_data as it is to do ldr r0, =(0x8250CB8 +1).

    Addressing your questions about what I've said last time, 0xValue is just a name I came up with. It's supposed to be some arbitrary, valid, constant. Replace it with 0xA or 0x50 or whatever your favorite hex value is.

    mov r0, #0x50 @Sets r0 to be 0x50
    ldr r1, =(0x20370D0) @loads address of Lastresult into r1. I.e pointer to the value in 0x800D (last result)
    strh r0, [r1] @stores 2 bytes of whatever is in r0 into the address/location specified by r1. In this case stores 0x50 in the last result

    I hope you see what we're doing with the pointers/symbols/storing now. With that out of the way I can address hooking.
    I'm going to explain assuming you already know what a hook is. You basically know that a hook is required when you're reworking or adding additional features to existing game code. In this case you're changing the damage of a move's power based on badges. Thus you're added a feature to existing game code. If you were to just paste your code over the existing code at that region, then obviously you would be overwriting some other important code. This is why we place a hook.

    Sometimes it's possible that the game code lends itself to be easily reworked and thus you just overwrite some existing bytes to do that (an example would be my "catch trainer's pokemon" thing). In these cases you don't need hooks (though it's kind of rare in comparison).
    I should warn you, to hook successfully into some routines are harder than others. You need to analyze the code at said routine and note to yourself which registers are free, which registers contain information you need after you hook and of course which register you will use for the hook. In complex functions you often don't have a lot of resources, so you need to draw conclusions based on what the analyzed code is like.

    Worst case scenario is usually that there's no registers you can use for the hook at the place you want to hook from. If that's the case you just hook early enough to a point where there are registers available and just derive their values and do your code from where you wanted to hook. OK, that last part doesn't make sense unless you've experienced what I'm talking about :P
    This last paragraph isn't that important anyways, just me rambling, lol.
     
  • 10,078
    Posts
    15
    Years
    • UK
    • Seen Oct 17, 2023
    OK, so when you do "ldr r0, move_data" you don't load it as a byte. move_data is a symbol which represents a pointer (in this case 0x8250CB8 + 1). We want a byte at that pointer so we do:
    ldr r0, move_data @load the actual pointer
    ldrb r0, [r0] @load a byte from the value of the pointer

    If you did ldrb r0, move_data, it would just take move_data as a hex value and load the first byte of it, rather than the first byte of the value it's pointing to (power).

    The rest of this is right. Also you seem to be confusing yourself with the names on the bottom. They're just definitions. It's the same thing to do ldr r0, move_data as it is to do ldr r0, =(0x8250CB8 +1).

    Addressing your questions about what I've said last time, 0xValue is just a name I came up with. It's supposed to be some arbitrary, valid, constant. Replace it with 0xA or 0x50 or whatever your favorite hex value is.

    mov r0, #0x50 @Sets r0 to be 0x50
    ldr r1, =(0x20370D0) @loads address of Lastresult into r1. I.e pointer to the value in 0x800D (last result)
    strh r0, [r1] @stores 2 bytes of whatever is in r0 into the address/location specified by r1. In this case stores 0x50 in the last result

    I hope you see what we're doing with the pointers/symbols/storing now. With that out of the way I can address hooking.
    Spoiler:

    Ok thanks, I'll fix up those bits about ldr :). I think I'm clearer on what's happening now after rereading SQ's and your tutorials (in particular, looking at definitions and patterns of coding).

    With the hook, I was worried exactly where I'd be needing it. In my head I still think in terms of scripts I'm afraid >< checking flags is easy in scripts, so I didn't see any need to hook. I think I'm going to drop the badges thing for now and instead focus on getting the change done.

    So my routine so far does half it's job, once I've added the 0x5 how do I get it to store at the location? Storing at the variable seemed easy enough, but then again that's RAM location not ROM, I tried using strb to get it back to 8250cb9, but that seems illogical anyway (and didn't work).
     
    Status
    Not open for further replies.
    Back
    Top