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

Code: ASM Resource Thread

Squeetz

ROM Hacker
191
Posts
10
Years
  • [FR] Synchronize overworld effect
    In Emerald and forward, if you have a Pok?mon with Synchronize at the front of the party, you'd have a 50% chance of encountering a Pok?mon of the same Nature. Here it is in Firered (albeit a bit messy):

    Spoiler:
     

    AkameTheBulbasaur

    Akame Marukawa of Iyotono
    409
    Posts
    10
    Years
  • [FR] Synchronize overworld effect
    In Emerald and forward, if you have a Pok?mon with Synchronize at the front of the party, you'd have a 50% chance of encountering a Pok?mon of the same Nature. Here it is in Firered (albeit a bit messy):

    Spoiler:

    (for some reason my text didn't save the first time)

    I tried this and it checks the ability just fine, branches when it should, and gets the Synchronize Pokemon's nature, but when I battle and catch the Pokemon, the nature of the caught Pokemon isn't the same as Synchronize's when it should be (I even set 127 to 0 so it would happen 100% of the time).

    Does it work on a clean ROM for you (or is it just me?)
     
    Last edited:

    Squeetz

    ROM Hacker
    191
    Posts
    10
    Years
  • (for some reason my text didn't save the first time)

    I tried this and it checks the ability just fine, branches when it should, and gets the Synchronize Pokemon's nature, but when I battle and catch the Pokemon, the nature of the caught Pokemon isn't the same as Synchronize's when it should be (I even set 127 to 0 so it would happen 100% of the time).

    Does it work on a clean ROM for you (or is it just me?)

    Not sure what to tell you, because it works for me.
    Did you script a wild battle and test it that way? Iirc, the Pok?mon generated from setwildbattle does not run through this function.
     

    AkameTheBulbasaur

    Akame Marukawa of Iyotono
    409
    Posts
    10
    Years
  • Not sure what to tell you, because it works for me.
    Did you script a wild battle and test it that way? Iirc, the Pok?mon generated from setwildbattle does not run through this function.

    I just used a normal wild encounter (ran through some grass and caught the first thing that appeared). I might test this some more when I get time and see if there's a specific thing I added which is conflicting because it might affect others who have the same feature.

    At least it's not the routine itself, though.
     
    325
    Posts
    10
    Years
  • So some guy and I were bored and wanted pokemon to have their EVs get calculated after every battle so here it is for FR.
    Code:
    .thumb
    @0000 0000 1100 1101
    @0000 0001 1001 1010 0x19A
    
    .macro get_attr
    	bl 0x03FBE8
    .endm
    
    .macro load_deoxys_species
    	mov r1, #0xCD
    	lsl r1, #1
    .endm
    
    .org 0x044674
    main:
    	push {r4-r7, lr}
    	mov r5, r0 @pokemon struct
    	mov r6, r1 @which stat to update
    	mov r1, #0xB @species, also r0 is still the same so it's ok
    	mov r2, #0
    	get_attr
    	load_deoxys_species
    	cmp r0, r1
    	beq load_atk
    	mov r1, #0x1C @size_of(pokemon_base)
    	mul r0, r1 @multiply to get the right base
    	ldr r1, pokemon_base
    	add r0, r1
    	mov r7, r0 @r7 is the correct pokemon base.
    	b 0x0446A0 @end
    load_atk:
    	ldr r0, deoxys_atk_base_pointer
    	mov r7, r0
    	b 0x0446A0 @end
    
    .align 2
    pokemon_base: .word 0x08254784
    
    .org 0x0446BA
    	mov r2, r7
    	lsl r1, r6, #1
    	add r1, r2
    	ldrb r1, [r1]
    
    .org 0x0446FE
    	pop {r4-r7} @you can change this to pop {r4-r7, pc}
    		@that gives you 6 free bytes to work with if you
    		@decompile the entire routine
    
    .org 0x044704
    deoxys_atk_base_pointer: .word deoxys_atk_base + 0x08000000
    
    .org 0x25E026
    deoxys_atk_base:
    .byte 0x32, 0xB4, 0x14, 0x96, 0xB4, 0x14
     

    AtecainCorp.

    Rejishan awake...
    1,377
    Posts
    15
    Years
  • Here's my Rock Climb script, just posting here for convenience. It's worth noting this script was made for FireRed, and uses JPAN's special 0x7F; of course, you can just compile the routine and replace special 0x7F with callasm instead.

    For Emerald, I believe you need to change the pointer to evaluator to be 0x081A8D95, as well as changing the movement bytes and the animation (?). Special 0x8F isn't in Emerald afaik, so just replace instances of it with getplayerpos 0x8004 0x8005 (EDIT: it seems to not work if it isnt a special, so it's still easiest to replace one of the specials which point to a nop to point to the routine instead).

    All instances of 0xA5 should be replaced with the Rock Climb behaviour byte, and all instances of 0x1AF with your attack ID for Rock Climb.

    This works for any height of Rock Climb wall, provided each Rock Climb wall tile has the behaviour byte specified in this script. You should also assign this script to the behaviour byte, as well as for the field move, so it's multipurpose in that sense. The script could probably be far more efficient, the movement isn't ideal, the "Rock Climb can't be used here" isn't consistent with how trying to Surf where you cannot works, and (due to horizontal Rock Climbing being impossible / ugly with the Gen 3's 2D engine) horizontal movement doesn't work, but for all intents and purposes it's functional.

    Code:
    #dynamic 0x800000
    
    '---------------
    #org @start
    lock
    special 0x8F
    comparefarbytetobyte 0x2036E50 0x11
    if 0x1 call @snippet1
    comparefarbytetobyte 0x2036E50 0x22
    if 0x1 call @snippet2
    special 0x7F
    compare 0x8005 0xA5
    if 0x1 goto @snippet3
    goto @snippet4
    
    '---------------
    #org @snippet1
    addvar 0x8005 0x1
    return
    
    '---------------
    #org @snippet2
    subvar 0x8005 0x1
    return
    
    '---------------
    #org @snippet3
    lock
    special 0x8F
    comparefarbytetobyte 0x2036E50 0x33
    if 0x1 goto @snippet5
    comparefarbytetobyte 0x2036E50 0x44
    if 0x1 goto @snippet5
    checkattack 0x1AF
    compare LASTRESULT 0x6
    if 0x1 goto @snippet5
    setanimation 0x0 LASTRESULT
    bufferpartypokemon 0x0 LASTRESULT
    bufferattack 0x1 0x1AF
    msgbox @string1 MSG_YESNO '"The wall is very rocky[.]\nWould y..."
    compare LASTRESULT 0x0
    if 0x1 goto @snippet6
    msgbox @string2 MSG_KEEPOPEN '"[buffer1] used [buffer2]!"
    closeonkeypress
    doanimation 0x2
    waitstate
    special 0x8F
    setvar 0x8006 0x0
    copyvar 0x4001 0x8004
    copyvar 0x4002 0x8005
    comparefarbytetobyte 0x2036E50 0x11
    if 0x1 goto @snippet7
    comparefarbytetobyte 0x2036E50 0x22
    if 0x1 goto @snippet8
    goto @snippet4
    
    '---------------
    #org @snippet4
    msgbox @string3 MSG_NORMAL '"Rock Climb can't be used here!"
    release
    end
    
    '---------------
    #org @snippet5
    msgbox @string4 MSG_SIGN '"The wall is very rocky[.]\nWill a ..."
    release
    end
    
    '---------------
    #org @snippet6
    closeonkeypress
    release
    end
    
    '---------------
    #org @snippet7
    copyvar 0x8004 0x4001
    addvar 0x4002 0x1
    copyvar 0x8005 0x4002
    addvar 0x8006 0x1
    special 0x7F
    compare 0x8005 0xA5
    if 0x1 goto @snippet7
    goto @snippet9
    
    '---------------
    #org @snippet8
    copyvar 0x8004 0x4001
    subvar 0x4002 0x1
    copyvar 0x8005 0x4002
    addvar 0x8006 0x1
    special 0x7F
    compare 0x8005 0xA5
    if 0x1 goto @snippet8
    goto @snippet9
    
    '---------------
    #org @snippet9
    compare 0x8006 0x0
    if 0x1 goto @snippet10
    comparefarbytetobyte 0x2036E50 0x11
    if 0x1 call @snippet11
    comparefarbytetobyte 0x2036E50 0x22
    if 0x1 call @snippet12
    subvar 0x8006 0x1
    goto @snippet9
    
    '---------------
    #org @snippet10
    release
    end
    
    '---------------
    #org @snippet11
    applymovement MOVE_PLAYER @move1
    waitmovement 0x0
    return
    
    '---------------
    #org @snippet12
    applymovement MOVE_PLAYER @move2
    waitmovement 0x0
    return
    
    
    '---------
    ' Strings
    '---------
    #org @string1
    = The wall is very rocky[.]\nWould you like to use [buffer2]?
    
    #org @string2
    = [buffer1] used [buffer2]!
    
    #org @string3
    = Rock Climb can't be used here!
    
    #org @string4
    = The wall is very rocky[.]\nWill a Pok?mon's move scale it?
    
    
    '-----------
    ' Movements
    '-----------
    #org @move1
    #raw 0x35 'Slide Down (Normal)
    #raw 0xFE 'End of Movements
    
    #org @move2
    #raw 0x36 'Slide Up (Normal)
    #raw 0xFE 'End of Movements

    Give credit, of course, to JPAN and FBI agent.

    I tried using this on Pokemon RUby. And IDK why still it says me "You can't use Rock CLimb Here"
     
    22
    Posts
    9
    Years
    • Seen Feb 1, 2020
    All you need to do is insert the code at a free location, edit the pointer at code + 0x164 to (pointer to code + 0x0179) and then call it with the callASM command followed by a waitstate. You also need to be in a locked state, so use lockall or lock before callASM, and release/releaseall at the end of the script.
    To change the location of where the box is located change X at code+2 and Y at code+4 and to change the width of the box change the byte at code+6.

    I don't know exactly what u mean when u say: "edit the pointer at code + 0x164 to (pointer to code + 0x0179)"
    Also, the end of the routine says : update_addr: .word update_box + rom). What i'm supposed to do with this, I can't compile it without changing it.
     
    22
    Posts
    9
    Years
    • Seen Feb 1, 2020
    Once u compile it, go to that offset in hxd, then goto that offset+0x164, change it to xxxxxx, where xxxxxx is offset where u compiled+0x179...
    It's pretty self explanatory...

    I did it before but it didn't work, so I thought I'm doing something wrong and I asked you. By the way, it still don't work for me, also the thumb compiler displays 2 errors at compiling: "failed to get real start of function: create_string" and "failed to get real start of function: get_max_digit"
    Then it makes a file with a bunch of 00 bytes followed by the assembled code
     
    5,256
    Posts
    16
    Years
  • Does this version I rewrote a while back work better for you guys?

    Code:
    .thumb
    .thumb_func
    
    .equ start, 0x08XXXXXX @ Change this to the start offset of the insertion location
    
    /*input:
    0x8008: first 16bits of x
    0x8009: second 16bits of x
    where x = max value allowed
    
    output: 0x8008: first 16bits of user input
    0x8009: second 16bits of user input
    0x800D: the digit A was pressed on (0x7f if B was pressed to cancel)*/
    
    make_box:
        push {r4-r7,lr}
        mov r0, #0x12 /*X position of box, in characters*/
        mov r1, #0xA /*Y position of box, in characters*/
        mov r2, #0xA /*size of box, in characters*/
        mov r3, #0x2
        ldr r4, =(0x0809D654+1) @ draw_interior
        bl call_via_r4
        add r6, r0, #0x0
        mov r1, #0x0
        ldr r2, =(0x080F7750+1) @ draw_border
        bl call_via_r2
        
        mov r0, #0x0
        mov r1, #0x0
        add r2, r6, #0x0
        bl create_and_print_string
        
        sub SP, SP, #0xc
        mov r0, #0x10
        str r0, [SP]
        mov r0, #0x1
        str r0, [SP, #0x4]
        mov r0, #0x0
        str r0, [SP, #0x8]
        add r0, r6, #0x0
        mov r1, #0x2
        mov r2, #0x0
        mov r3, #0x2
        ldr r4, =(0x0810F7D8+1) @ func_10F7D8
        bl call_via_r4
        add SP, SP, #0xC
        
        mov r0, #0x0
        mov r1, #0x1
        add r2, r6, #0x0
        mov r3, #0xff
        bl set_update_function
        
        mov r0, #0x0
        ldr r1, =(0x080F67A4+1) @ set_ab58
        bl call_via_r1
        
        pop {r4-r7, pc}
    
    /*This function creates the string representation of the
    number box and places it on fcode_buffer2 1. The number contains
    an arrow pointing at the currently selected digit, the number
    to be printed and some padding zeros if the number has less
    digits than the max value set at 0x8008/9 variables.
    params
    r0 = num to display
    r1 = digit with arrow*/
    .align 2
    create_string:
        push {r4-r7, lr}
        add r6, r0, #0x0
        add r5, r1, #0x0
        bl get_max_digit
        add r4, r0, #0x0
    
        ldr r0, fcode_buffer2
        add r1, r6, #0x0
        mov r2, #0x0
        add r3, r4, #0x0
        push {r4}
        ldr r4, =(0x08008E78+1) @ int_to_str
        bl call_via_r4
        pop {r4}
        ldr r0, fcode_buffer2
        ldr r1, =(0x08008E08+1) @ str_len
        bl call_via_r1
        
        add r1, r4, #0x0
        ldr r2, fcode_buffer2
        add r3, r5, #0x0
        bl copy_and_pad_string
        pop {r4-r7, pc}
    
    .align 2
    get_max_digit:
        ldr r3, var_8008
        ldr r2, [r3]
        cmp r2, #0x0
        bne set_count_digits
        ldr r2, decimal_table
        mov r0, #0x9
        lsl r1, r0, #0x2
        add r1, r1, r2
        ldr r1, [r1]
        sub r1, #0x1
        str r1, [r3]
        mov pc, lr
        
    set_count_digits:
        mov r0, #0x9
        ldr r3, decimal_table
    count_digit_loop:
        lsl r1, r0, #0x2
        add r1, r3, r1
        ldr r1, [r1]
        cmp r1, r2
        bhi count_digit_loop_cont
        add r0, #0x1
        mov pc, lr
    count_digit_loop_cont:    
        sub r0, #0x1
        b count_digit_loop
    
    copy_and_pad_string:
        push {r4-r7,lr}
        add r7, r2, #0x0
        add r6, r3, #0x0
        add r5, r1, #0x1
        sub r4, r0, #0x1
        
        mov r0, #0xff
        strb r0, [r7, r5]
        sub r5, #0x1
        
    str_build_loop:
        cmp r6, #0x0
        beq add_arrow
        cmp r4, #0x0
        blt padd_with_zero
        
        ldrb r0, [r7, r4]
        strb r0, [r7, r5]
        
        b str_build_loop_dec
    add_arrow:
        mov r0, #0x7B
        strb r0, [r7, r5]
        add r4, #0x1
        b str_build_loop_dec
        
    padd_with_zero:
        mov r0, #0xA1
        strb r0, [r7, r5]
        
        
    str_build_loop_dec:
        sub r6, #0x1
        sub r4, #0x1
        sub r5, #0x1
        cmp r5, #0x0
        bge str_build_loop
        pop {r4-r7, pc}
    
    
    set_update_function:
        push {r4-r7, lr}
        add r4, r0, #0x0
        add r5, r1, #0x0
        add r6, r2, #0x0
        add r7, r3, #0x0
        ldr r0, update_addr
        mov r1, #0x50
        ldr r2, =(0x0807741C+1) @ task_add
        bl call_via_r2
        add r3, r0, #0x0
        lsl r0,r0, #0x2
        add r0, r0, r3
        lsl r0, r0, #0x3
        ldr r1, tasks
        add r1, r0, r1
        strb r4, [r1, #0x10]
        strb r5, [r1, #0x11]
        strb r6, [r1, #0x12]
        strb r7, [r1, #0x13]
        mov r0, #0x0
        str r0, [r1, #0x14]
        bl get_max_digit
        ldr r1, RAM_menu_addr
        strb r0, [r1, #0x4]
        mov r0, #0x0
        strb r0, [r1, #0x2]
        
        
        pop {r4-r7,pc}
    
    /*r0 = function index in queue
    function params
    0x12 (byte) = box id
    0x14 (word) = number counter*/
    
    update_box:
        push {r4-r6,lr}
        add r6, r0, #0x0
        ldr r5, tasks
        lsl r0, r6, #0x2
        add r0, r0, r6
        lsl r0, r0, #0x3
        add r5, r0, r5
        ldr r4, RAM_menu_addr
        
        ldr r0, super
        ldrh r3, [r0, #0x2e]
        
        mov r0, #0x1
        and r0, r3
        cmp r0, #0x0
        bne pressed_a
        
        mov r0, #0x2
        and r0, r3
        cmp r0, #0x0
        bne pressed_b
        
        mov r0, #0x10
        and r0, r3
        cmp r0, #0x0
        bne pressed_right
        
        mov r0, #0x20
        and r0, r3
        cmp r0, #0x0
        bne pressed_left
        
        mov r0, #0x40
        and r0, r3
        cmp r0, #0x0
        bne pressed_up
        
        mov r0, #0x80
        and r0, r3
        cmp r0, #0x0
        bne pressed_down
        
        pop {r4-r6,pc}
        
    pressed_a:
        ldr r1, var_8008
        ldr r0, [r5, #0x14]
        str r0, [r1]
        ldr r1, var_800D
        ldrb r0, [r4, #0x2]
        strh r0, [r1]
        b update_clean_function
        
    pressed_b:
        ldr r1, var_800D
        mov r0, #0x7f
        strh r0, [r1]
        
    update_clean_function:    
        ldr r1, clean_addr
        ldrb r0, [r5, #0x12]
        mov pc, r1
    
    pressed_left:
        ldrb r0, [r4, #0x2]
        add r0, #0x1
        ldrb r1, [r4, #0x4]
        cmp r0, r1
        blt set_direction
        mov r0, #0x0
        b set_direction
        
    pressed_right:
        ldrb r0, [r4, #0x2]
        sub r0, #0x1
        cmp r0, #0x0
        bge set_direction
        ldrb r0, [r4, #0x4]
        sub r0, #0x1
        
    set_direction:
        strb r0, [r4, #0x2]
        add r1, r0, #0x0
        ldr r0, [r5, #0x14]
        ldrb r2, [r5, #0x12]
        bl create_and_print_string
        pop {r4-r6,pc}
        
    pressed_up:
        ldr r1, decimal_table
        ldrb r0, [r4, #0x2]
        lsl r0, r0, #0x2
        add r1, r0, r1
        ldr r1, [r1]
        ldr r0, [r5, #0x14]
        add r0, r1, r0
        b check_min
        
    pressed_down:
        ldr r1, decimal_table
        ldrb r0, [r4, #0x2]
        lsl r0, r0, #0x2
        add r1, r0, r1
        ldr r1, [r1]
        ldr r0, [r5, #0x14]
        sub r0, r0, r1
        
    check_min:
        cmp r0, #0x0
        bge check_max
        mov r0, #0x0
        
    check_max:
        ldr r1, var_8008
        ldr r1, [r1]
        cmp r0, r1
        ble set_number
        add r0, r1, #0x0
        
    set_number:
        str r0, [r5, #0x14]
        ldrb r1, [r4, #0x2]
        ldrb r2, [r5, #0x12]
        bl create_and_print_string
        pop {r4-r6,pc}
    
    create_and_print_string:
        push {lr}
        push {r2}
        bl create_string
        
        pop {r0}
        sub SP, SP, #0xC
        mov r2, #0x2
        str r2, [SP]
        mov r2, #0x0
        str r2, [sp, #0x4]
        mov r2, #0x0
        str r2, [sp, #0x8]
        mov r1, #0x2
        ldr r2, fcode_buffer2
        mov r3, #0x8
        ldr r4, =(0x08002C48+1) @ print_string
        bl call_via_r4
        add SP, SP, #0xC
        pop {pc}
    
    call_via_r1:
        bx r1
    
    call_via_r2:
        bx r2
    
    call_via_r4:
        bx r4    
        
    .align 2    
    fcode_buffer2: .word 0x02021CD0
    var_8008: .word 0x020370C8
    var_800D: .word 0x020370D0
    RAM_menu_addr: .word 0x0203ADE4
    tasks: .word 0x03005090
    super: .word 0x030030F0
    clean_addr: .word 0x0809CD2E
    decimal_table: .word 0x08231E3C    
    update_addr: .word (update_box + start +1)
     
    5,256
    Posts
    16
    Years
  • Here you go.^^

    Okay, the rom symbol is not 0x800001, it's 0x08000001. You never need to change it. Similarly, the location symbol doesn't need the start 08.

    I think that is the only issue:

    Code:
    .thumb
    
    .equ location,              0x1669F8
    .equ rom,                   0x08000001
    
    .equ ability_name_length,   0x0D
    .equ base_stats_length,     0x1C
    .equ pokemon_length,        0x64
    .equ req_species,           0x0B
    .equ req_ability,           0x2E
    .equ ability1,              0x16
    .equ ability2,              0x17
    
    .org location
    ability_capsule:
        push {lr}
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        ldr r2, item_function_ptr
        ldr r1, =(rom + dp05_abilitycapsule)
        str r1, [r2]
        ldr r3, item_consume_maybe
        bl call_via_r3
        pop {r3}
        bx r3
    
    dp05_abilitycapsule:
        push {r4-r7,lr}
        mov r6, r1
        lsl r0, r0, #0x18
        lsr r5, r0, #0x18
    
    get_selected_pokemon:
        ldr r0, brm
        ldrb r0, [r0, #9]
        mov r1, #pokemon_length
        mul r0, r1
        ldr r1, party_player
        add r4, r0, r1    
    
    get_species:
        mov r0, r4
        mov r1, #req_species
        ldr r3, get_attr
        bl call_via_r3
    
    compare_abilities:
        ldr r1, base_stats_ptr
        ldr r1, [r1]
        mov r2, #base_stats_length
        mul r0, r2
        add r1, r0
        ldrb r0, [r1, #ability1]
        ldrb r1, [r1, #ability2]
        cmp r0, r1
        beq fail
        cmp r0, #0
        beq fail
        cmp r1, #0
        beq fail
        mov r4, #0
        b continue
    
    fail:
        mov r4, #1
    
    continue:
        mov r0, #5
        ldr r3, audio_play
        bl call_via_r3
        cmp r4, #0
        beq effect
    
    no_effect:
        mov r0, #0
        strb r0, [r1]
        ldr r0, no_effect_str
        mov r1, #1
        ldr r3, item_menu_string
        bl call_via_r3
        mov r0, #2
        ldr r3, bgid_mark_for_sync
        bl call_via_r3
        ldr r1, tasks
        lsl r0, r5, #2
        add r0, r0, r5
        lsl r0, r0, #3
        add r0, r0, r1
        mov r1, r6
        str r1, [r0]
        b end
    
    effect:
        mov r0, r5
        ldr r3, item_use_animation
        bl call_via_r3
        ldr r1, item_function_ptr
        ldr r0, =(rom + abilitycapsule_use)
        str r0, [r1]
        b end
    
    abilitycapsule_use:
        push {r4-r7,lr}
        lsl r0, r0, #0x18
        lsr r5, r0, #0x18
    
    get_selected_pokemon_again:
        ldr r0, brm
        ldrb r0, [r0, #9]
        mov r1, #pokemon_length
        mul r0, r1
        ldr r1, party_player
        add r4, r0, r1
    
    get_ability_id_again:
        mov r0, r4
        mov r1, #req_ability
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
    
    invert_ability_id:
        mov r1, #1
        eor r0, r1
        ldr r2, var_800D
        strb r0, [r2]
    
    set_new_ability_id:
        mov r0, r4
        mov r1, #req_ability
        ldr r3, set_attr
        bl call_via_r3
    
    set_item_effectiveness:
        mov r0, #1
        ldr r1, item_effectiveness
        strb r0, [r1]
    
    remove_item:
        ldr r0, var_800E
        ldrh r0, [r0]
        mov r1, #1
        ldr r3, bag_remove_item
        bl call_via_r3
    
    buffer_nickname:
        mov r0, r4
        ldr r1, fcode_buffer2
        ldr r3, buffer_pkmn_nick
        bl call_via_r3
    
    buffer_ability_name:
        mov r0, r4
        ldr r1, fcode_buffer3
        ldr r3, =(rom + buffer_ability)
        bl call_via_r3
    
    construct_string:
        ldr r4, displayed_string
        mov r0, r4
        ldr r1, =(rom + abilitycapsule_str)
        ldr r3, fdecoder
        bl call_via_r3
    
    print_string:
        mov r0, r4
        mov r1, #1
        ldr r3, item_menu_string
        bl call_via_r3
    
    display_box:
        mov r0, #2
        ldr r3, bgid_mark_for_sync
        bl call_via_r3
    
    add_callback_task:
        ldr r1, tasks
        mov r2, r5
        lsl r0, r2, #2
        add r0, r0, r5
        lsl r0, r0, #3
        add r0, r0, r1
        ldr r1, item_menu_callback
        str r1, [r0]
        b end
    
    buffer_ability:
        push {r4-r7,lr}
        mov r4, r0
        mov r5, r1
    
    get_species_again:
        mov r1, #req_species
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r6, r0, #0x10
    
    get_ability_bit:
        mov r0, r4
        mov r1, #req_ability
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x18
        lsr r1, r0, #0x18
    
    get_ability_id:
        mov r0, r6
        mov r2, #base_stats_length
        mul r0, r2
        ldr r2, base_stats_ptr
        ldr r2, [r2]
        add r2, r0
        add r2, #ability1
        ldrb r0, [r2, r1]
    
    get_ability_name_string:
        mov r1, #ability_name_length
        mul r0, r1
        ldr r1, ability_names_ptr
        ldr r1, [r1]
        add r1, r0
        mov r0, r5
        ldr r3, strcpy_xFF_terminated
        bl call_via_r3
        
    end:
        pop {r4-r7}
        pop {r3}
    
    call_via_r3:
        bx r3
    
    abilitycapsule_str:
        .byte 0x00
        .byte 0xFD, 0x02, 0x00, 0xC0, 0xF4, 0xDC, 0xDD, 0xDB, 0xDF, 0xD9, 0xDD, 0xE8, 0xFE, 0xF4, 0xE2, 0xD8, 0xD9, 0xE6, 0xE8, 0xD9, 0x00, 0xE7, 0xDD, 0xD7, 0xDC, 0x00, 0xEE, 0xE9, 0x00, 0xFD, 0x03, 0xAB, 0x09, 0xFF, 0xFC, 0x09, 0xFF
        
    .align 2    
        fcode_buffer2:          .word 0x02021CD0 @buffer2 ok
        fcode_buffer3:          .word 0x02021CF0
        displayed_string:       .word 0x02021D18 @string adress ok
        party_player:           .word 0x02024284 @ok
        var_800D:               .word 0x020370D0 @vars ok
        var_800E:               .word 0x0203AD30 @vars ok
        brm:                    .word 0x0203B0A0
        item_effectiveness:     .word 0x0203B0C0
    
        tasks:                  .word 0x03004FE0 @ENG: 0x03005090
        item_function_ptr:      .word 0x03005DE8 @ENG: 0x03005E98 @ok
    
        base_stats_ptr:         .word 0x080001BC @ENG gleich
        ability_names_ptr:      .word 0x080001C0 @ENG gleich
        strcpy_xFF_terminated:  .word 0x08008D04|1 @ENG: 0x08008D84|1 @ok
        fdecoder:               .word 0x08008F4C|1 @ENG: 0x08008FCC|1 @ok
        get_attr:               .word 0x0803FAE8|1 @ENG: 0x0803FBE8|1 @ok
        set_attr:               .word 0x0804027C|1 @ENG: 0x0804037C|1 @ok
        audio_play:             .word 0x08072230|1 @ENG: 0x080722CC|1 @ok
        bag_remove_item:        .word 0x0809A2BC|1 @ENG: 0x0809A1D8|1 @ok
        item_consume_maybe:     .word 0x080A17BC|1 @ENG: 0x080A16D0|1 @ok
        bgid_mark_for_sync:     .word 0x080F6A38|1 @ENG: 0x080F67A4|1 @ok
        buffer_pkmn_nick:       .word 0x08120314|1 @ENG: 0x081202E0|1 @ok
        item_menu_string:       .word 0x0812032C|1 @ENG: 0x081202F8|1 @ok
        item_use_animation:     .word 0x08124E10|1 @ENG: 0x08124DC0|1 @ok
        item_menu_callback:     .word 0x0812560C|1 @ENG: 0x081255BC|1 @ok
        no_effect_str:          .word 0x08416824 @ENG: 0x084169DC @ "Es wird keine Wirkung haben."
     
    22
    Posts
    9
    Years
    • Seen Feb 1, 2020
    Does this version I rewrote a while back work better for you guys?

    Code:
    .thumb
    .thumb_func
    
    .equ start, 0x08XXXXXX @ Change this to the start offset of the insertion location
    
    /*input:
    0x8008: first 16bits of x
    0x8009: second 16bits of x
    where x = max value allowed
    
    output: 0x8008: first 16bits of user input
    0x8009: second 16bits of user input
    0x800D: the digit A was pressed on (0x7f if B was pressed to cancel)*/
    
    make_box:
        push {r4-r7,lr}
        mov r0, #0x12 /*X position of box, in characters*/
        mov r1, #0xA /*Y position of box, in characters*/
        mov r2, #0xA /*size of box, in characters*/
        mov r3, #0x2
        ldr r4, =(0x0809D654+1) @ draw_interior
        bl call_via_r4
        add r6, r0, #0x0
        mov r1, #0x0
        ldr r2, =(0x080F7750+1) @ draw_border
        bl call_via_r2
        
        mov r0, #0x0
        mov r1, #0x0
        add r2, r6, #0x0
        bl create_and_print_string
        
        sub SP, SP, #0xc
        mov r0, #0x10
        str r0, [SP]
        mov r0, #0x1
        str r0, [SP, #0x4]
        mov r0, #0x0
        str r0, [SP, #0x8]
        add r0, r6, #0x0
        mov r1, #0x2
        mov r2, #0x0
        mov r3, #0x2
        ldr r4, =(0x0810F7D8+1) @ func_10F7D8
        bl call_via_r4
        add SP, SP, #0xC
        
        mov r0, #0x0
        mov r1, #0x1
        add r2, r6, #0x0
        mov r3, #0xff
        bl set_update_function
        
        mov r0, #0x0
        ldr r1, =(0x080F67A4+1) @ set_ab58
        bl call_via_r1
        
        pop {r4-r7, pc}
    
    /*This function creates the string representation of the
    number box and places it on fcode_buffer2 1. The number contains
    an arrow pointing at the currently selected digit, the number
    to be printed and some padding zeros if the number has less
    digits than the max value set at 0x8008/9 variables.
    params
    r0 = num to display
    r1 = digit with arrow*/
    .align 2
    create_string:
        push {r4-r7, lr}
        add r6, r0, #0x0
        add r5, r1, #0x0
        bl get_max_digit
        add r4, r0, #0x0
    
        ldr r0, fcode_buffer2
        add r1, r6, #0x0
        mov r2, #0x0
        add r3, r4, #0x0
        push {r4}
        ldr r4, =(0x08008E78+1) @ int_to_str
        bl call_via_r4
        pop {r4}
        ldr r0, fcode_buffer2
        ldr r1, =(0x08008E08+1) @ str_len
        bl call_via_r1
        
        add r1, r4, #0x0
        ldr r2, fcode_buffer2
        add r3, r5, #0x0
        bl copy_and_pad_string
        pop {r4-r7, pc}
    
    .align 2
    get_max_digit:
        ldr r3, var_8008
        ldr r2, [r3]
        cmp r2, #0x0
        bne set_count_digits
        ldr r2, decimal_table
        mov r0, #0x9
        lsl r1, r0, #0x2
        add r1, r1, r2
        ldr r1, [r1]
        sub r1, #0x1
        str r1, [r3]
        mov pc, lr
        
    set_count_digits:
        mov r0, #0x9
        ldr r3, decimal_table
    count_digit_loop:
        lsl r1, r0, #0x2
        add r1, r3, r1
        ldr r1, [r1]
        cmp r1, r2
        bhi count_digit_loop_cont
        add r0, #0x1
        mov pc, lr
    count_digit_loop_cont:    
        sub r0, #0x1
        b count_digit_loop
    
    copy_and_pad_string:
        push {r4-r7,lr}
        add r7, r2, #0x0
        add r6, r3, #0x0
        add r5, r1, #0x1
        sub r4, r0, #0x1
        
        mov r0, #0xff
        strb r0, [r7, r5]
        sub r5, #0x1
        
    str_build_loop:
        cmp r6, #0x0
        beq add_arrow
        cmp r4, #0x0
        blt padd_with_zero
        
        ldrb r0, [r7, r4]
        strb r0, [r7, r5]
        
        b str_build_loop_dec
    add_arrow:
        mov r0, #0x7B
        strb r0, [r7, r5]
        add r4, #0x1
        b str_build_loop_dec
        
    padd_with_zero:
        mov r0, #0xA1
        strb r0, [r7, r5]
        
        
    str_build_loop_dec:
        sub r6, #0x1
        sub r4, #0x1
        sub r5, #0x1
        cmp r5, #0x0
        bge str_build_loop
        pop {r4-r7, pc}
    
    
    set_update_function:
        push {r4-r7, lr}
        add r4, r0, #0x0
        add r5, r1, #0x0
        add r6, r2, #0x0
        add r7, r3, #0x0
        ldr r0, update_addr
        mov r1, #0x50
        ldr r2, =(0x0807741C+1) @ task_add
        bl call_via_r2
        add r3, r0, #0x0
        lsl r0,r0, #0x2
        add r0, r0, r3
        lsl r0, r0, #0x3
        ldr r1, tasks
        add r1, r0, r1
        strb r4, [r1, #0x10]
        strb r5, [r1, #0x11]
        strb r6, [r1, #0x12]
        strb r7, [r1, #0x13]
        mov r0, #0x0
        str r0, [r1, #0x14]
        bl get_max_digit
        ldr r1, RAM_menu_addr
        strb r0, [r1, #0x4]
        mov r0, #0x0
        strb r0, [r1, #0x2]
        
        
        pop {r4-r7,pc}
    
    /*r0 = function index in queue
    function params
    0x12 (byte) = box id
    0x14 (word) = number counter*/
    
    update_box:
        push {r4-r6,lr}
        add r6, r0, #0x0
        ldr r5, tasks
        lsl r0, r6, #0x2
        add r0, r0, r6
        lsl r0, r0, #0x3
        add r5, r0, r5
        ldr r4, RAM_menu_addr
        
        ldr r0, super
        ldrh r3, [r0, #0x2e]
        
        mov r0, #0x1
        and r0, r3
        cmp r0, #0x0
        bne pressed_a
        
        mov r0, #0x2
        and r0, r3
        cmp r0, #0x0
        bne pressed_b
        
        mov r0, #0x10
        and r0, r3
        cmp r0, #0x0
        bne pressed_right
        
        mov r0, #0x20
        and r0, r3
        cmp r0, #0x0
        bne pressed_left
        
        mov r0, #0x40
        and r0, r3
        cmp r0, #0x0
        bne pressed_up
        
        mov r0, #0x80
        and r0, r3
        cmp r0, #0x0
        bne pressed_down
        
        pop {r4-r6,pc}
        
    pressed_a:
        ldr r1, var_8008
        ldr r0, [r5, #0x14]
        str r0, [r1]
        ldr r1, var_800D
        ldrb r0, [r4, #0x2]
        strh r0, [r1]
        b update_clean_function
        
    pressed_b:
        ldr r1, var_800D
        mov r0, #0x7f
        strh r0, [r1]
        
    update_clean_function:    
        ldr r1, clean_addr
        ldrb r0, [r5, #0x12]
        mov pc, r1
    
    pressed_left:
        ldrb r0, [r4, #0x2]
        add r0, #0x1
        ldrb r1, [r4, #0x4]
        cmp r0, r1
        blt set_direction
        mov r0, #0x0
        b set_direction
        
    pressed_right:
        ldrb r0, [r4, #0x2]
        sub r0, #0x1
        cmp r0, #0x0
        bge set_direction
        ldrb r0, [r4, #0x4]
        sub r0, #0x1
        
    set_direction:
        strb r0, [r4, #0x2]
        add r1, r0, #0x0
        ldr r0, [r5, #0x14]
        ldrb r2, [r5, #0x12]
        bl create_and_print_string
        pop {r4-r6,pc}
        
    pressed_up:
        ldr r1, decimal_table
        ldrb r0, [r4, #0x2]
        lsl r0, r0, #0x2
        add r1, r0, r1
        ldr r1, [r1]
        ldr r0, [r5, #0x14]
        add r0, r1, r0
        b check_min
        
    pressed_down:
        ldr r1, decimal_table
        ldrb r0, [r4, #0x2]
        lsl r0, r0, #0x2
        add r1, r0, r1
        ldr r1, [r1]
        ldr r0, [r5, #0x14]
        sub r0, r0, r1
        
    check_min:
        cmp r0, #0x0
        bge check_max
        mov r0, #0x0
        
    check_max:
        ldr r1, var_8008
        ldr r1, [r1]
        cmp r0, r1
        ble set_number
        add r0, r1, #0x0
        
    set_number:
        str r0, [r5, #0x14]
        ldrb r1, [r4, #0x2]
        ldrb r2, [r5, #0x12]
        bl create_and_print_string
        pop {r4-r6,pc}
    
    create_and_print_string:
        push {lr}
        push {r2}
        bl create_string
        
        pop {r0}
        sub SP, SP, #0xC
        mov r2, #0x2
        str r2, [SP]
        mov r2, #0x0
        str r2, [sp, #0x4]
        mov r2, #0x0
        str r2, [sp, #0x8]
        mov r1, #0x2
        ldr r2, fcode_buffer2
        mov r3, #0x8
        ldr r4, =(0x08002C48+1) @ print_string
        bl call_via_r4
        add SP, SP, #0xC
        pop {pc}
    
    call_via_r1:
        bx r1
    
    call_via_r2:
        bx r2
    
    call_via_r4:
        bx r4    
        
    .align 2    
    fcode_buffer2: .word 0x02021CD0
    var_8008: .word 0x020370C8
    var_800D: .word 0x020370D0
    RAM_menu_addr: .word 0x0203ADE4
    tasks: .word 0x03005090
    super: .word 0x030030F0
    clean_addr: .word 0x0809CD2E
    decimal_table: .word 0x08231E3C    
    update_addr: .word (update_box + start +1)

    Finally it works!!!! Thank you.
    In this new version is necessary to change the pointer at 0x164?
    Now, the last thing, how can I use it in a script, I mean, how to store the numbers in variables?

    Edit: I figured out how to use it but the use of variable 0x8009 is buggy, when i set the number I want it just make a bug and make impossible to use the number selector, so I only can use the variable 0x8008
     
    Last edited:
    5,256
    Posts
    16
    Years
  • [FR] EV-reducing Berries

    Find 0x49C bytes of free space at a word-aligned address, and take note of it.
    Set the EV-reducing berries' Type to Type 1 ("Out of battle").
    Set the items' Field script pointers to the address you noted, plus 1.
    Set the items' Battle script pointer to 0xA2239.
    Assemble the following routine, changing 0xXXXXXX to the address you noted (not plus 1).
    Open the generated .bin file, navigate to the location address, and select 0x49C bytes.
    Copy the bytes and paste them in your ROM, at the same address.

    Code:
    [FONT="Source Code Pro"].thumb
    
    @ -- Change these
    .equ start_address, 0x29B110
    @ --
    
    .equ rom, 0x08000000
    
    .equ pokemon_length, 0x64
    
    .equ req_species,           0x0B
    .equ req_held_item,         0x0C
    .equ req_hp_ev,             0x1A
    .equ req_atk_ev,            0x1B
    .equ req_def_ev,            0x1C
    .equ req_spe_ev,            0x1D
    .equ req_spatk_ev,          0x1E
    .equ req_spdef_ev,          0x1F
    .equ req_happiness,         0x20
    .equ req_catch_location,    0x23
    .equ req_pokeball,          0x26
    
    .equ item_luxuryball,   0x0B
    .equ item_pomegberry,   0x99
    .equ item_kelpsyberry,  0x9A
    .equ item_qualotberry,  0x9B
    .equ item_hondewberry,  0x9C
    .equ item_grepaberry,   0x9D
    .equ item_tomatoberry,  0x9E
    .equ item_soothebell,   0xB8
    
    .org start_address, 0xFF
    ev_berries:
        push {lr}
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        ldr r2, item_function_ptr
        ldr r1, =(rom + dp05_ev_berries + 1)
        str r1, [r2]
        ldr r3, item_consume_maybe
        bl call_via_r3
        pop {r3}
    
    call_via_r3:
        bx r3
    
    .align 2
        item_consume_maybe:     .word 0x080A16D0|1
        .pool
    
    dp05_ev_berries:
        push {r4-r7,lr}
        mov r7, r10
        mov r6, r9
        mov r5, r8
        push {r5-r7}
        sub sp, sp, #0xC
        str r1, [sp, #0]
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        mov r10, r0
    
    get_selected_pokemon:
        ldr r4, brm
        ldrb r1, [r4, #9]
        mov r0, #pokemon_length
        mul r1, r0
        ldr r0, party_player
        add r5, r1, r0
    
    determine_berry:
        ldr r0, var_800E
        ldrh r0, [r0]
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        sub r0, #(item_pomegberry - 1)
        mov r7, r0
    
    get_ev_req: 
        mov r0, r5
        mov r1, r7
        ldr r3, =(rom + get_ev_req_from_berry_id + 1)
        bl call_via_r3
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        cmp r0, #0
        beq no_effect
        mov r6, r0
    
    happiness_before:
        mov r0, r5
        mov r1, #req_happiness
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        ldr r1, var_8000
        strh r0, [r1]
    
    ev_value_before:
        mov r0, r5
        mov r1, r6
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        ldr r1, var_8001
        strh r0, [r1]
    
    use_berry:
        mov r0, r5
        mov r1, r6
        ldr r3, =(rom + use_ev_berry + 1)
        bl call_via_r3
        lsl r0, r0, #0x18
        lsr r4, r0, #0x18
    
    ev_after:
        mov r0, r5
        mov r1, r6
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        mov r8, r0
    
    happiness_after:
        mov r0, r5
        mov r1, #req_happiness
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        mov r9, r0
    
    branch_for_effectiveness:
        cmp r4, #0
        bne no_effect
        ldr r0, var_8000
        ldrh r0, [r0]
        cmp r0, r9
        bne effect
        ldr r1, var_8001
        ldrh r1, [r1]
        cmp r1, r8
        bne effect
    
    no_effect:
        ldr r1, item_effectiveness
        mov r0, #0
        strb r0, [r1]
        mov r0, #5
        ldr r3, audio_play
        bl call_via_r3
        ldr r0, no_effect_str
        mov r1, #1
        ldr r3, item_menu_string
        bl call_via_r3
        mov r0, #2
        ldr r3, bgid_mark_for_sync
        bl call_via_r3
        ldr r1, tasks
        mov r2, r10
        lsl r0, r2, #2
        add r0, r10
        lsl r0, r0, #3
        add r0, r0, r1
        ldr r1, [sp]
        str r1, [r0]
        b end
     
    effect:
        mov r0, r10
        ldr r3, item_use_animation
        bl call_via_r3
        ldr r1, item_function_ptr
        ldr r0, =(rom + berry_use + 1)
        str r0, [r1]
      
    end:
        add sp, sp, #0xC
        pop {r3-r5}
        mov r8, r3
        mov r9, r4
        mov r10, r5
        pop {r4-r7}
        pop {r0}
        bx r0
    
    .align 2
        item_function_ptr:      .word 0x03005E98
        .pool
    
    berry_use:
        push {r4-r7,lr}
        lsl r0, r0, #0x18
        lsr r5, r0, #0x18
        ldr r1, item_effectiveness
        mov r0, #1
        strb r0, [r1]
    
    sound_fx:
        mov r0, #1
        ldr r3, audio_play
        bl call_via_r3
    
    remove_item:
        ldr r0, var_800E
        ldrh r0, [r0]
        mov r1, #1
        ldr r3, bag_remove_item
        bl call_via_r3
    
    get_selected_pokemon_again:
        ldr r4, brm
        ldrb r1, [r4, #9]
        mov r0, #pokemon_length
        mul r1, r0
        ldr r0, party_player
        add r4, r1, r0
    
    determine_berry_again:
        ldr r0, var_800E
        ldrh r0, [r0]
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        sub r0, #(item_pomegberry - 1)
        mov r7, r0
    
    get_ev_req_again: 
        mov r0, r4
        mov r1, r7
        ldr r3, =(rom + get_ev_req_from_berry_id + 1)
        bl call_via_r3
        lsl r0, r0, #0x18
        lsr r1, r0, #0x18
    
    ev_after_again:
        mov r0, r4
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        mov r8, r0
    
    happiness_after_again:
        mov r0, r4
        mov r1, #req_happiness
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        mov r9, r0
    
    buffer_pkmn_nick_to_buffer2:
        ldr r1, fcode_buffer2
        mov r0, r4
        ldr r3, buffer_pkmn_nick
        bl call_via_r3
    
    buffer_stat_name_to_buffer3:
        ldr r1, fcode_buffer3
        mov r0, r7
        ldr r3, =(rom + buffer_stat_name + 1)
        bl call_via_r3
    
    branch_for_string:
        ldr r0, var_8000
        ldrh r0, [r0]
        cmp r0, r9
        beq happiness_at_max
        ldr r0, var_8001
        ldrh r0, [r0]
        cmp r0, r8
        beq ev_at_0
    
    happiness_not_at_max_ev_above_0:
        ldr r0, displayed_string
        ldr r1, =(rom + happiness_not_at_max_ev_above_0_str)
        ldr r3, fdecoder
        bl call_via_r3
        b load_displayed_string
    
    ev_at_0:
        ldr r0, displayed_string
        ldr r1, =(rom + happiness_up_ev_cant_fall_str)
        ldr r3, fdecoder
        bl call_via_r3
        b load_displayed_string
    
    happiness_at_max:
        ldr r0, displayed_string
        ldr r1, =(rom + adore_ev_down_str)
        ldr r3, fdecoder
        bl call_via_r3
    
    load_displayed_string:
        ldr r0, displayed_string
    
    print_item_message:
        mov r1, #1
        ldr r3, item_menu_string
        bl call_via_r3
        mov r0, #2
        ldr r3, bgid_mark_for_sync
        bl call_via_r3
        ldr r1, tasks
        mov r2, r5
        lsl r0, r2, #2
        add r0, r0, r5
        lsl r0, r0, #3
        add r0, r0, r1
        ldr r1, item_menu_callback
        str r1, [r0]
        pop {r4-r7}
        pop {r0}
        bx r0
    
    .align 2
    get_ev_req_from_berry_id:
        push {r4-r7,lr}
        mov r4, r0
        lsl r1, r1, #0x18
        lsr r1, r1, #0x18
        lsl r1, r1, #2
        ldr r0, =(rom + ev_switch_table)
        add r0, r0, r1
        ldr r0, [r0]
        mov pc, r0 @ switch jump
    
    .align 2
    ev_switch_table:
        .word (rom + ev_switch_default)
        .word (rom + case_ev_hp)
        .word (rom + case_ev_atk)
        .word (rom + case_ev_def)
        .word (rom + case_ev_spatk)
        .word (rom + case_ev_spdef)
        .word (rom + case_ev_spe)
    
    .align 2
    ev_switch_default:
    case_ev_hp:
        mov r0, #req_hp_ev
        b return_ev_req
    
    case_ev_atk:
        mov r0, #req_atk_ev
        b return_ev_req
    
    case_ev_def:
        mov r0, #req_def_ev
        b return_ev_req
    
    case_ev_spe:
        mov r0, #req_spe_ev
        b return_ev_req
    
    case_ev_spatk:
        mov r0, #req_spatk_ev
        b return_ev_req
    
    case_ev_spdef:
        mov r0, #req_spdef_ev
        b return_ev_req
    
    ev_return_0:
        mov r0, #0
    
    return_ev_req:
        pop {r4-r7}
        pop {r1}
        bx r1
    
    .align 2
    buffer_stat_name:
        push {lr}
        mov r2, r1
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        cmp r0, #6
        bgt return_stat_name
        ldr r1, =(rom + stat_name_switch_table)
        lsl r0, r0, #2
        add r0, r0, r1
        ldr r0, [r0]
        mov pc, r0 @ switch jump
    
    stat_name_switch_table:
        .word (rom + stat_name_default)
        .word (rom + case_hp_name)
        .word (rom + case_atk_name)
        .word (rom + case_def_name)
        .word (rom + case_spatk_name)
        .word (rom + case_spdef_name)
        .word (rom + case_spe_name)
    
    stat_name_default:
    case_hp_name:
        ldr r1, hp_name_str
        b break_stat_name_switch
    
    case_atk_name:
        ldr r1, atk_name_str
        b break_stat_name_switch
    
    case_def_name:
        ldr r1, def_name_str
        b break_stat_name_switch
    
    case_spe_name:
        ldr r1, spe_name_str
        b break_stat_name_switch
    
    case_spatk_name:
        ldr r1, spatk_name_str
        b break_stat_name_switch
    
    case_spdef_name:
        ldr r1, spdef_name_str
    
    break_stat_name_switch:
        mov r0, r2
        ldr r3, strcpy_xFF_terminated
        bl call_via_r3
    
    return_stat_name:
        pop {r0}
        bx r0
    
    .align 2
    use_ev_berry:
        push {r4-r7,lr}
        mov r7, r10
        mov r6, r9
        mov r5, r8
        push {r5-r7}
        lsl r1, r1, #0x18
        lsr r1, r1, #0x18
        mov r8, r0
        mov r7, r1
    
    get_relevant_ev_value:
        mov r0, r8
        mov r1, r7
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
    
    check_ev:
        cmp r0, #0
        ble set_ev_unchanged_flag
    
    subtract_ev:
        mov r1, r0
        sub r0, #10
        cmp r0, r1
        blo set_ev
        mov r0, #0
    
    set_ev:
        mov r2, sp
        strh r0, [r2]
        mov r0, r8
        mov r1, r7
        ldr r3, set_attr
        bl call_via_r3
    
    recalc_stats:
        mov r0, r8
        ldr r3, recalculate_stats
        bl call_via_r3
        b get_happiness_value
    
    set_ev_unchanged_flag:
        mov r6, #1
    
    get_happiness_value:
        mov r0, r8
        mov r1, #req_happiness
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
    
    check_happiness:
        cmp r0, #255
        beq check_if_should_return_1
        cmp r0, #199
        bgt add_two_happiness
        cmp r0, #99
        bgt add_five_happiness
    
    add_ten_happiness:
        mov r6, #10
        b remember_new_happiness
    
    add_five_happiness:
        mov r6, #5
        b remember_new_happiness
    
    add_two_happiness:
        mov r6, #2
    
    remember_new_happiness:
        add r5, r6, r0
    
    luxuryball_check:
        mov r0, r8
        mov r1, #req_pokeball
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        cmp r0, #item_luxuryball
        bne metlocation_check
    
    luxuryball_bonus:
        add r5, #1
        add r6, #1
    
    metlocation_check:
        mov r0, r8
        mov r1, #req_catch_location
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        mov r4, r0
        ldr r3, sav1_map_get_name
        bl call_via_r3
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        cmp r4, r0
        bne soothebell_check
    
    metlocation_bonus:
        add r5, #1
        add r6, #1
    
    soothebell_check:
        mov r0, r8
        mov r1, #req_held_item
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        mov r1, #item_soothebell
        cmp r0, r1
        bne add_happiness
    
    soothebell_bonus:
        lsr r0, r6, #1
        add r5, r0
    
    add_happiness:
        mov r0, r5
        cmp r0, #255
        ble set_happiness
        mov r0, #255
    
    set_happiness:
        mov r2, sp
        strh r0, [r2]
        mov r0, r8
        mov r1, #req_happiness
        ldr r3, set_attr
        bl call_via_r3
    
    return_0:
        mov r0, #0
        b finish_using_ev_berry
    
    check_if_should_return_1:
        cmp r5, #1
        bne return_0
    
    return_1:
        mov r0, #1
    
    finish_using_ev_berry:
        pop {r3-r5}
        mov r8, r3
        mov r9, r4
        mov r10, r5
        pop {r4-r7}
        pop {r1}
        bx r1
    
    happiness_not_at_max_ev_above_0_str:
        .byte 0xFD, 0x02, 0x00, 0xE8, 0xE9, 0xE6, 0xE2, 0xD9, 0xD8, 0x00, 0xDA, 0xE6, 0xDD, 0xD9, 0xE2, 0xD8, 0xE0, 0xED, 0xAD, 0xFE, 0xCE, 0xDC, 0xD9, 0x00, 0xD6, 0xD5, 0xE7, 0xD9, 0x00, 0xFD, 0x03, 0x00, 0xDA, 0xD9, 0xE0, 0xE0, 0xAB, 0xFC, 0x09, 0xFF
        @ "[PKMN] turned friendly.[NEWLINE]The base [STAT] fell![WAITKEYPRESS]"
    
    happiness_up_ev_cant_fall_str:
        .byte 0xFD, 0x02, 0x00, 0xE8, 0xE9, 0xE6, 0xE2, 0xD9, 0xD8, 0x00, 0xDA, 0xE6, 0xDD, 0xD9, 0xE2, 0xD8, 0xE0, 0xED, 0xAD, 0xFE, 0xCE, 0xDC, 0xD9, 0x00, 0xD6, 0xD5, 0xE7, 0xD9, 0x00, 0xFD, 0x03, 0x00, 0xD7, 0xD5, 0xE2, 0xB4, 0xE8, 0x00, 0xDA, 0xD5, 0xE0, 0xE0, 0xAB, 0xFC, 0x09, 0xFF
        @ "[PKMN] turned friendly.[NEWLINE]The base [STAT] can't fall![WAITKEYPRESS]"
    
    adore_ev_down_str:
        .byte 0xFD, 0x02, 0x00, 0xD5, 0xD8, 0xE3, 0xE6, 0xD9, 0xE7, 0x00, 0xED, 0xE3, 0xE9, 0xAB, 0xFE, 0xCE, 0xDC, 0xD9, 0x00, 0xD6, 0xD5, 0xE7, 0xD9, 0x00, 0xFD, 0x03, 0x00, 0xDA, 0xD9, 0xE0, 0xE0, 0xAB, 0xFC, 0x09, 0xFF
        @ "[PKMN] adores you![NEWLINE]The base [STAT] fell![WAITKEYPRESS]"
    
    .align 2
        fcode_buffer2:          .word 0x02021CD0
        fcode_buffer3:          .word 0x02021CF0
        displayed_string:       .word 0x02021D18
        party_player:           .word 0x02024284
        var_8000:               .word 0x020370B8
        var_8001:               .word 0x020370BA
        var_800E:               .word 0x0203AD30
        brm:                    .word 0x0203B0A0
        item_effectiveness:     .word 0x0203B0C0
    
        tasks:                  .word 0x03005090
    
        strcpy_xFF_terminated:  .word 0x08008D84|1
        fdecoder:               .word 0x08008FCC|1
        recalculate_stats:      .word 0x0803E47C|1
        get_attr:               .word 0x0803FBE8|1
        set_attr:               .word 0x0804037C|1
        sav1_map_get_name:      .word 0x08056260|1
        audio_play:             .word 0x080722CC|1
        bag_remove_item:        .word 0x0809A1D8|1
        bgid_mark_for_sync:     .word 0x080F67A4|1
        buffer_pkmn_nick:       .word 0x081202E0|1
        item_menu_string:       .word 0x081202F8|1
        item_use_animation:     .word 0x08124DC0|1
        item_menu_callback:     .word 0x081255BC|1
        hp_name_str:            .word 0x084169C2 @ "HP"
        spatk_name_str:         .word 0x084169C5 @ "SP. ATK"
        spdef_name_str:         .word 0x084169CD @ "SP. DEF"
        atk_name_str:           .word 0x08417674 @ "ATTACK"
        def_name_str:           .word 0x0841767B @ "DEFENSE"
        spe_name_str:           .word 0x0841768D @ "SPEED"
        no_effect_str:          .word 0x084169DC @ "It won't have any effect."
    
    [/FONT]

    The Soothe Bell multiplier acts as it does in Generation IV and onwards (meaning it will also multiply bonuses from the met location and Luxury Ball).

    This will introduce the Pomeg Glitch; see tkim's post here on how to fix it.
     

    Attachments

    • ev_berries.asm
      13.4 KB · Views: 36
    Last edited:
    232
    Posts
    12
    Years
    • Seen Sep 10, 2019

    [FR] EV-reducing Berries


    Can't wait to try this out! Thanks!

    I have two questions though. Can I assume that the luxury ball mentioned in the routine affects the happiness the berries give out? Does the routine also check if the player is at the same location as the berry user's met location and if the berry user is holding a soothe bell at the time (unless Emerald's behaves otherwise)? Here's where my questions are based from: https://bulbapedia.bulbagarden.net/wiki/Friendship#Boosting_friendship
    Sorry if I'm overwhelming you.
     
    Last edited by a moderator:
    5,256
    Posts
    16
    Years
  • Can't wait to try this out! Thanks!

    I have two questions though. Can I assume that the luxury ball mentioned in the routine affects the happiness the berries give out? Does the routine also check if the player is at the same location as the berry user's met location and if the berry user is holding a soothe bell at the time (unless Emerald's behaves otherwise)? Here's where my questions are based from: https://bulbapedia.bulbagarden.net/wiki/Friendship#Boosting_friendship
    Sorry if I'm overwhelming you.

    Ah, I forgot about those bonuses. I've updated the routine to consider both, and used the Gen IV+ method of the Soothe Bell. Thanks for bringing that to my attention!
     
    232
    Posts
    12
    Years
    • Seen Sep 10, 2019
    Ah, I forgot about those bonuses. I've updated the routine to consider both, and used the Gen IV+ method of the Soothe Bell. Thanks for bringing that to my attention!

    If I wanted to use the Gen III method of the Soothe Bell, can I just rearrange the soothebell check/bonus and change the 'b' conditions to come before the other checks?

    edit: here's what I did: is this okay, or do I have to change registers too?
    Code:
    remember_new_happiness:
        add r5, r5, r0
    
    [COLOR=DarkOrange]soothebell_check:
        mov r0, r8
        mov r1, #req_held_item
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        mov r1, #item_soothebell
        cmp r0, r1
        [COLOR=Blue]bne luxuryball_check[/COLOR]
    
    soothebell_bonus:
        lsr r0, r5, #1
        add r5, r0[/COLOR]
    
    luxuryball_check:
        mov r0, r8
        mov r1, #req_pokeball
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        cmp r0, #item_luxuryball
        bne metlocation_check
    
    luxuryball_bonus:
        add r5, #1
    
    metlocation_check:
        mov r0, r8
        mov r1, #req_catch_location
        mov r2, #0
        ldr r3, get_attr
        bl call_via_r3
        mov r4, r0
        ldr r3, sav1_map_get_name
        bl call_via_r3
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        cmp r4, r0
       [COLOR=Blue] bne add_happiness[/COLOR]
    
    metlocation_bonus:
        add r5, #1
    
    add_happiness:
        mov r0, r5
        cmp r0, #255
        ble set_happiness
        mov r0, #255
     
    Last edited:
    5,256
    Posts
    16
    Years
  • If I wanted to use the Gen III method of the Soothe Bell, can I just rearrange the soothebell check/bonus and change the 'b' conditions to come before the other checks?

    edit: here's what I did: is this okay, or do I have to change registers too?

    Yeah, that should work. The registers shouldn't need changing as far as I can tell. Best way to know is to test yourself and have a script that buffers the Pokémon's friendship so you can test; that's what I did.
     
    Back
    Top