• 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
  • Age 26
  • 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
  • Age 26
  • 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
  • Age 26
  • 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