• 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.

Blah

Free supporter
  • 1,924
    Posts
    11
    Years
    Hm it still ended up with the same error, I'm guessing it's still a register clash - at least its not just aborting now though I suppose!

    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    
    main: 
    	lsr r7, r0, #0x18
    	mov r0, r9
    	ldrb r1, [r0] /*replacements for bits my hook overwrites*/
    	push {r0-r3}
    	mov r2, #0xFF
    	lsl r2, r0, #0x6
    	add r2, #0xC0
    	ldr r3, =(0x806E454 +1)
    	bl linker
    	ldrh r3, [r0]
    	add r3, #0x4
    	strh r3, [r0]
    	pop {r0-r3}
    	ldr r0, =(0x80d83f0 +1)
    	bx r0
    
    .align 2
    linker:
    	bx r3
    Oh wow, I see now. The original code does a "bl" to 0x80D83F0 +1. You're doing a bx.

    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    
    main: 
    	lsr r7, r0, #0x18
    	mov r0, r9
    	ldrb r1, [r0] /*replacements for bits my hook overwrites*/
    	push {r0-r3}
    	mov r2, #0xFF
    	lsl r2, r0, #0x6
    	add r2, #0xC0
    	ldr r3, =(0x806E454 +1)
    	bl linker
    	ldrh r3, [r0]
    	add r3, #0x4
    	strh r3, [r0]
    	pop {r0-r3}
    	ldr r0, =(0x80d83f0 +1)
    	bl linker2
    	ldr r2, =(0x80D788A +1)
    	bx r2
    
    .align 2
    linker:
    	bx r3
    
    linker2:
    	bx r0
     

    daniilS

    busy trying to do stuff not done yet
  • 409
    Posts
    10
    Years
    • Seen Jan 29, 2024
    I told him to use bx because it seems the bl there is only used because it's of a long range
     
  • 10,078
    Posts
    15
    Years
    • UK
    • Seen Oct 17, 2023
    Back again! :) Less of a problem now, slightly different routine too - this one is trying to add 0x1 to variable 0x4080

    If my read variable / write to variable section written correctly? In game the rest works (including the strb r1, [r2] - which goes to RAM) and there are no bad effects, but var 0x4080 doesn't gain 1.

    Spoiler:
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Back again! :) Less of a problem now, slightly different routine too - this one is trying to add 0x1 to variable 0x4080

    If my read variable / write to variable section written correctly? In game the rest works (including the strb r1, [r2] - which goes to RAM) and there are no bad effects, but var 0x4080 doesn't gain 1.

    Spoiler:

    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    
    main: 
    	push {r2, r3}
    [B]	mov r0, #0xFF
    	lsl r0, r0, #0x6
    	add r0, #0xC0
    	ldr r3, =(0x806E454 +1)
    	bl linker
    	ldrh r1, [r0]
    	add r1, r1, #0x1
    	strh r1, [r0][/B]
    	pop {r2, r3}
    	mov r1, #0x1
    	strb r1, [r2]
    	ldr r0, =(0x8022498 +1)
    	bx r0
    
    .align 2
    linker:
    	bx r3

    The var address getting takes only one paramater, the var number. So, by definition of how these functions are made, r0 must contain the var number before the call. You're setting r1 to 0x4080, when it should be r0.

    Secondly, you need to push r2 and r3 before the the modifications. While r1 and r0 are safe to modify (in this specific case), r2 and r3 are not. That means you need to push them, so you can recall their values for after the hook.
     
  • 10,078
    Posts
    15
    Years
    • UK
    • Seen Oct 17, 2023
    Welcome to the Magic is a noob thread

    Reading bytes is straight forward, but some data is stored differently. I'm looking to read data that is stored in the style of what I assume everyone is calling little endian these days? :P idk.

    Anyway, map tiles are stored with the tile number and the permissions combined. So... tile 0x10C with no permission (0x1) is stored as 0C 02. How can I account for this in a routine that is trying to find the tile number only?
     

    Touched

    Resident ASMAGICIAN
  • 625
    Posts
    9
    Years
    • Age 122
    • Seen Feb 1, 2018
    Welcome to the Magic is a noob thread

    Reading bytes is straight forward, but some data is stored differently. I'm looking to read data that is stored in the style of what I assume everyone is calling little endian these days? :P idk.

    Anyway, map tiles are stored with the tile number and the permissions combined. So... tile 0x10C with no permission (0x1) is stored as 0C 02. How can I account for this in a routine that is trying to find the tile number only?

    What you want is called masking. Essentially, the permission and tile number are stored together in a 16 bit word. The tile number is stored in the lower 10 bits of this word, and the meta data (permissions) are in the upper 6. To get the 10 bits out, you use what is called a bit mask. Say for example I have 0x1253 and want the lower ten bits. 0x1253 in binary (padded to 16 bits) is

    Code:
    0001 0010 0101 0011

    Now, we select a mask. Everywhere we want a bit to "pass through" we put a 1, and everywhere we want to ignore a bit we put 0. So a mask for the lower 10 bits is

    Code:
    0000 0011 1111 1111

    This is 3FF in hex.

    Now we do logical AND:
    0x1253 & 0x3FF = 0x253

    What's happening is very clear when you look at the binary

    Code:
         0001 0010 0101 0011
    AND  0000 0011 1111 1111
    ------------------------
    =    0000 0010 0101 0011

    You can use the THUMB op AND to do this. It looks like
    Code:
    and Rd, Rs
    and there are no variations, so you'll have to MOV in (or LDR if its is bigger than 8 bits) your mask.
     

    kearnseyboy6

    Aussie's Toughest Mudder
  • 300
    Posts
    15
    Years
    • Seen Jun 22, 2019
    Wow, masking is very logical. May I ask why this won't work:

    lsl 0x6
    lsr 0x6

    then you will have the same result?
     

    Touched

    Resident ASMAGICIAN
  • 625
    Posts
    9
    Years
    • Age 122
    • Seen Feb 1, 2018
    Wow, masking is very logical. May I ask why this won't work:

    lsl 0x6
    lsr 0x6

    then you will have the same result?

    That won't work because a register is 32 bits. You would need to

    Code:
    lsl Rd, #0x16 @ (16 + 6)
    lsr Rd, #0x16

    However, I was just trying to introduce a common concept to extract bits rather than show the most efficient way. Masking is more useful when you have non-consecutive bits that you want to extract.
     

    Joexv

    ManMadeOfGouda joexv.github.io
  • 1,037
    Posts
    11
    Years
    Ok so I'm having... issues....
    This is my first actual routine so be nice.:P
    Spoiler:


    All it's supposed to do is get the value stored in 0x8000
    multiply it by 0x1c then add 0x14 and then add 0x1 to read both bytes of a pokemons egg group into 2 seperate variables to be buffered.

    This is what I'm getting as a result:
    Spoiler:


    What am I doing wrong??
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    All it's supposed to do is get the value stored in 0x8000
    multiply it by 0x1c then add 0x14 and then add 0x1 to read both bytes of a pokemons egg group into 2 seperate variables to be buffered.

    What am I doing wrong??

    Hey, I'm lead to believe your script is what's wrong here. The routine does what you say it should do, though inefficiently. Try posting your script here or in the script help thread. Anyways, here's the body of a more efficient version.

    Code:
    ldr r2, =(0x20370B8)
    ldrh r0, [r2]
    mov r1, #0x1C
    mul r0, r0, r1
    ldr r1, =(0x8254784 +0x14)
    add r0, r0, r1
    ldrb r1, [r0, #0x1]
    ldrb r0, [r0]
    ldr r3, =(0x20370BA)
    strb r0, [r2]
    strb r1, [r3]

    0x8000: group 1
    0x8001: group 2
     

    Joexv

    ManMadeOfGouda joexv.github.io
  • 1,037
    Posts
    11
    Years
    Hey, I'm lead to believe your script is what's wrong here. The routine does what you say it should do, though inefficiently. Try posting your script here or in the script help thread. Anyways, here's the body of a more efficient version.

    Code:
    ldr r2, =(0x20370B8)
    ldrh r0, [r2]
    mov r1, #0x1C
    mul r0, r0, r1
    ldr r1, =(0x8254784 +0x14)
    add r0, r0, r1
    ldrb r1, [r0, #0x1]
    ldrb r0, [r0]
    ldr r3, =(0x20370BA)
    strb r0, [r2]
    strb r1, [r3]

    0x8000: group 1
    0x8001: group 2
    Wow yea that's wy smaller and way neater.
    but the script is super simple so that's why I thought it was the asm:
    Spoiler:
     
  • 218
    Posts
    10
    Years
    • Seen Nov 12, 2021
    Hi,
    I found the routine of the battle command C1 (hidden power), I wanted to write a far more simple routine to just return the type of the user (wich I think I have), and, if it is needed, the power (fixe)

    Here is the hidden power routine :
    Spoiler:



    I don't want to someone translate the routine, but, does someone know what it returns ? I mean, It supposed to determine type and power, but in the end it pop five register. So how they're used ?
    Or there only R0 that is used ? If so, how the data are stored in ?
    I know there's a lot of question but I read tutorials since hours but I am not able to understand this one x)
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Hi,
    I found the routine of the battle command C1 (hidden power), I wanted to write a far more simple routine to just return the type of the user (wich I think I have), and, if it is needed, the power (fixe)

    Here is the hidden power routine :
    Spoiler:



    I don't want to someone translate the routine, but, does someone know what it returns ? I mean, It supposed to determine type and power, but in the end it pop five register. So how they're used ?
    Or there only R0 that is used ? If so, how the data are stored in ?
    I know there's a lot of question but I read tutorials since hours but I am not able to understand this one x)

    What ROM base? This isn't FireRed :o
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Yeah indeed. Forgot to mention this is Emerald x)

    Well, taking a look at this code atm, I can tell that it doesn't have a return value. Instead, it seems to write into some sort of data structure/RAM pointer.

    You'd be best off setting break points at these hard coded RAM offsets and seeing what they are. When they're written directly like this, rather than loaded from pointers, it means the RAM addresses are static. So if you can see what they hold, you can generalize what that RAM offset will always hold (in 99% of cases).
     
  • 218
    Posts
    10
    Years
    • Seen Nov 12, 2021
    Thank's a lot for the time that you take
    But I actually found a post of Chaos Rush and he said he tried to right value/change pointer and so on and nothing happen, it's probably hard coded as he said.
    Sorry to make you waste your time :s
     
  • 218
    Posts
    10
    Years
    • Seen Nov 12, 2021
    Ok now I have other question, see this post in the spoiler. I would like to adapt the following routine to emerald but if only I could understand why it exactly doing in Firered it would be very very useful. So, the routine :

    Spoiler:

    My question are principally for the first routine, I mean transform type/get base power. Not the table item.
    In all likelihood I'll have question for the second one but for the moment, I'm sure the first one doesn't work correctly for me.
    The most important to me is understand what is happening, so I put my question/how I understand in bold.

    Last thing, I tried to find the RAM address for emerald and this is what I have

    .BattleData: .word 0x02024084
    .UserBank: .word 0x0202420B
    .BasePower: .word 0x020244E0
    .MemAddress: .word 0x0202449C
    .CurrentScript: .word 0x02024214
    .FailScript: .word 0x082D9F1C
    .Outcome: .word 0x0202427C
    .BattleData: .word 0x02024084
    .TargetBank: .word 0x0202420C

    I know this is not the topic but the routine doesn't works for me. Perhaps simply because I don't have the correct offset.

    Thank's in advance whoever answer me :)

    I tried to make a routine that take my type and transform my attack into this type :

    Spoiler:


    It does absolutly nothing, the attack remind regular

    There is one good thing in this one, it actually change the type of the attack, but it's a little bit random. Didn't manage to do super effective damages.
    EDIT : Actually damages are always neutral, and it's not a question of string displayed. I tested the damage and they are really neutral. I guess it load a value that is too high but can't figured out how to load the good (primary type of my poke) :

    Spoiler:


    I don't know why, but this one works :

    Spoiler:


    Change attack in user's primary type
     
    Last edited:
  • 325
    Posts
    10
    Years
    What I'm trying to do is remake the rematch system in an extremely basic way, and here's the code I made for it.
    Spoiler:
    I'm only trying to add five levels to the Pokémon's levels(in this instance youngster ben), but after running the script it wasn't working, and his levels remained what they were before. Any idea what's going wrong?
     

    Touched

    Resident ASMAGICIAN
  • 625
    Posts
    9
    Years
    • Age 122
    • Seen Feb 1, 2018
    What I'm trying to do is remake the rematch system in an extremely basic way, and here's the code I made for it.
    Spoiler:
    I'm only trying to add five levels to the Pokémon's levels(in this instance youngster ben), but after running the script it wasn't working, and his levels remained what they were before. Any idea what's going wrong?

    I can't even tell what you are trying to do, but I'll do my best. It looks as though you are loading a ROM offset rather than an address. ROM is prefixed by 08/09, you have prefixed it with 00 (BIOS). In fact this address is invalid and will be ignored by VBA - the bios is only 16kb. Hardware will do weird things.

    Next, you load two half words, add 5, then load the addresses again? Why? I think what you are trying to do is store to those addresses, but you'd need str, strh or strb to do that. If I'm right about these being ROM offsets, then you clearly don't understand the concept of ROM. You can't right to it. Ever. There are a few bytes of ROM address space reserved for GPIO for sensors, and this is the only exception.

    Lastly, you're wasting stack space. Neither R0, R1 or LR need to be pushed.

    I suggest you read some tutorials and look at existing code so you actually understand what you're doing, rather than fumbling around in the dark.
     
    Status
    Not open for further replies.
    Back
    Top