The PokéCommunity Forums

The PokéCommunity Forums (https://www.pokecommunity.com/index.php)
-   Binary Hack Research & Development (https://www.pokecommunity.com/forumdisplay.php?f=195)
-   -   Code ASM Resource Thread (https://www.pokecommunity.com/showthread.php?t=339153)

mbcn10ww April 25th, 2017 5:13 PM

Quote:

Originally Posted by Wesley FG (Post 9628943)
the value of "indexes of male stone" is the item value ?

will have two dawn stone, one work in male and one work in female, it is correct ?

i not understand it well

the indexes are your Evolution indexes, one for male stone evo and one for female stone evo, the item index will only be chosen on your editor (G3HS, G3T...)

tkim April 29th, 2017 9:57 AM

Quote:

Originally Posted by FBI (Post 8536952)
In response to this:

Setting a random Secret and Trainer ID



Requires the insertion of Random Number generator
So apparently TID isn't set if you skip the intro, and I'm sure SID is probably also not set. The following routine will randomize them for you!


To insert:

There's some orange text here, set it to be the pointer to where you inserted the random number generator routine +1 (keep the 0x8 prefix, but don't reverse the pointer).

After you've fixed the pointer, compile and insert into free space.

Spoiler:

[code]
.text
.align 2
.thumb
.thumb_func

main:
push (r0-r3, lr}
ldr r0, .random
ldr r1, =(0x20370B8) @generate first half of ID
mov r2, #0xFF
lsl r2, r2, #0x8
add r2, r2, #0xFF
strh r2, [r1]
bl linker
mov r3, r0
ldr r1, =(0x20370B8) @generate second half of ID
mov r2, #0xFF
lsl r2, r2, #0x8
add r2, r2, #0xFF
strh r2, [r1]
push {r3}
bl linker
pop {r3}
lsl r0, r0, #0x10
lsr r3, r3, #0x10
orr r3, r3, r0
ldr r0, =(0x300500C)
ldr r0, [r0]
add r0, r0, #0xA
ldr r1, =(0x20370BA)
ldrb r1, [r1]
add r0, r0, r1
strh r3, [r0] @set ID
cmp r1, #0x1
bne setRam
pop {r0-r3, pc}

setRam:
ldr r1, =(0x2020000) @set RAM Pointer to TID
strh r3, [r1]
pop {r0-r3, pc}


linker:
bx r0


.align 2

.random:
.word 0x8[random]
[code]



Usage:

setvar 0x8001 0x0
callasm 0x[this routine +1]
setvar 0x8001 0x2
callasm 0x[this routine +1]

Call it twice like I have, setting var 0x8001 to 0x0 and 0x2 respectively, it will generate a random PID and SID.

Heyo, I can't seem to compile this. May you fix it please?

Spherical Ice April 30th, 2017 2:14 PM

[FR] Complimentary Premier Ball for purchases of over 9 Poké Balls



Ever since RSE, the Poké Mart clerk has thrown in a bonus Premier Ball when the player purchases at least 10 Poké Balls. This feature was absent from FireRed, however, presumably for accuracy reasons for the remake factor of the game. To implement this feature, simply assemble the following routine and place a pointer (+1) at x9BF64.

Code:

.thumb @ pointer+1 at 0809BF64

main:
    push {r4,r5,lr}
    lsl r0, r0, #0x18
    lsr r4, r0, #0x18
    lsl r0, r4, #2
    add r0, r0, r4
    lsl r0, r0, #3
    ldr r1, =(0x03005098) @ tasks.args
    add r5, r0, r1
    ldr r0, =(0x030030F0) @ super
    ldrh r1, [r0, #0x2E]
    mov r0, #0x3
    and r0, r1
    cmp r0, #0
    beq end

continue:
    mov r0, #5
    ldr r3, =(0x080722CC|1) @ audio_play
    bl call_via_r3
    mov r1, #0xA
    ldrh r0, [r5, r1]
    cmp r0, #0x4 @ Poké Ball item ID
    bne no_premier_ball
    mov r1, #2
    ldrh r0, [r5, r1]
    cmp r0, #0x9 @ Maximum quantity of Poké Balls to not qualify for a Premier Ball
    ble no_premier_ball
    mov r0, #0xC @ Premier Ball item ID
    mov r1, #1 @ Quantity to give
    ldr r3, =(0x0809A084|1) @ bag_add_item
    bl call_via_r3
    lsl r0, r0, #0x18
    lsr r0, r0, #0x18
    cmp r0, #1
    bne no_premier_ball
    ldr r1, =(0x08XXXXXX) @ Address of string: "I'll throw in a PREMIER BALL, too.[FC][09]"
    ldr r2, =(0x0809BF98|1)
    mov r0, r4
    ldr r3, =(0x0813F75C|1)
    bl call_via_r3
    b end

no_premier_ball:
    mov r0, r4
    ldr r3, =(0x0809BF98|1)
    bl call_via_r3

end:
    pop {r4,r5}
    pop {r0}
    bx r0

call_via_r3:
    bx r3


The routine specifies an address for the string "I'll throw in a PREMIER BALL, too." as 0x08XXXXXX. Replace this with the address at which you insert the following bytes:
Code:

C3 B4 E0 E0 00 E8 DC E6 E3 EB 00 DD E2 00 D5 00 CA CC BF C7 C3 BF CC 00 BC BB C6 C6 B8 00 E8 E3 E3 AD FC 09 FF


The same string, but with "PREMIER BALL" in title case (i.e. "Premier Ball"), has the following bytes:
Code:

C3 B4 E0 E0 00 E8 DC E6 E3 EB 00 DD E2 00 D5 00 CA E6 D9 E1 DD D9 E6 00 BC D5 E0 E0 B8 00 E8 E3 E3 AD FC 09 FF


As always with strings, it's recommended you place a byte after the FF delimiter at the end of the string to prevent tools which read FF bytes as free space from overwriting the string's delimiter and making the string bug.

Wesley FG May 5th, 2017 2:15 PM

Someone can convert this asm to EM
is a screen that display IV and EV screens is very usefull
https://www.pokecommunity.com/showpost.php?p=9229108&postcount=919
https://i869.photobucket.com/albums/ab256/jiangzhengwenjz/q_zpshnquzant.gif

tkim May 7th, 2017 9:09 PM

REQUEST for FR:

A 'givepokemon' routine that allows the user to set custom OT name and TID/SID. (useful for creating legal event pokemon)

tkim May 8th, 2017 2:43 PM

Quote:

Originally Posted by FBI (Post 8536952)
In response to this:

Setting a random Secret and Trainer ID



Requires the insertion of Random Number generator
So apparently TID isn't set if you skip the intro, and I'm sure SID is probably also not set. The following routine will randomize them for you!


To insert:

There's some orange text here, set it to be the pointer to where you inserted the random number generator routine +1 (keep the 0x8 prefix, but don't reverse the pointer).

After you've fixed the pointer, compile and insert into free space.

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func   

main:
    push (r0-r3, lr}
    ldr r0, .random
    ldr r1, =(0x20370B8) @generate first half of ID
    mov r2, #0xFF
    lsl r2, r2, #0x8
    add r2, r2, #0xFF
    strh r2, [r1]
    bl linker
    mov r3, r0
    ldr r1, =(0x20370B8) @generate second half of ID
    mov r2, #0xFF
    lsl r2, r2, #0x8
    add r2, r2, #0xFF
    strh r2, [r1]
    push {r3}
    bl linker
    pop {r3}
    lsl r0, r0, #0x10
    lsr r3, r3, #0x10
    orr r3, r3, r0
    ldr r0, =(0x300500C)
    ldr r0, [r0]
    add r0, r0, #0xA
    ldr r1, =(0x20370BA)
    ldrb r1, [r1]
    add r0, r0, r1
    strh r3, [r0] @set ID
    cmp r1, #0x1
    bne setRam
    pop {r0-r3, pc}

setRam:
    ldr r1, =(0x2020000) @set RAM Pointer to TID
    strh r3, [r1]
    pop {r0-r3, pc}

linker:
    bx r0

.align 2

.random:
    .word 0x8[random]





Usage:

setvar 0x8001 0x0
callasm 0x[this routine +1]
setvar 0x8001 0x2
callasm 0x[this routine +1]

Call it twice like I have, setting var 0x8001 to 0x0 and 0x2 respectively, it will generate a random PID and SID.

Can anyone confirm that this routine works? My game freezes when using this routine. His random number routine has been inserted. I changed the highlighted orange text from
Code:

.word 0x8[random]


to
Code:

.word 0x8800001



NewDenverCity May 9th, 2017 12:12 PM

Quote:

Originally Posted by tkim (Post 9641016)
Can anyone confirm that this routine works? My game freezes when using this routine. His random number routine has been inserted. I changed the highlighted orange text from
Code:

.word 0x8[random]


to
Code:

.word 0x8800001



Change [random] to 044EC8 + 1

tkim May 9th, 2017 2:46 PM

Quote:

Originally Posted by NewDenverCity (Post 9641956)
Change [random] to 044EC8 + 1

Tried it and didn't work. I think there's a problem with his routine.

Blah May 9th, 2017 3:51 PM

Eh, this routine is around the time when I first started. I'm currently very rusty on ASM and haven't tested the fix. Please try this:

Spoiler:

.thumb
.align 2

main:
push {r4-r5, lr}
ldr r5, =(0x300500C)
ldr r5, [r5]
ldr r4, rand
bl linker
strh r0, [r5, #0xC]
bl linker
strh r0, [r5, #0xA]
ldr r1, =(0x2020000)
strh r0, [r1]
pop {r4-r5, pc}

linker:
bx r4


.align 2
rand:
.word (0x08044EC8 + 1)



Untested, and may not compile as is. Post updates here please.

tkim May 9th, 2017 8:17 PM

Quote:

Originally Posted by FBI (Post 9642111)
Eh, this routine is around the time when I first started. I'm currently very rusty on ASM and haven't tested the fix. Please try this:

Spoiler:

.thumb
.align 2

main:
push {r4-r5, lr}
ldr r5, =(0x300500C)
ldr r5, [r5]
ldr r4, rand
bl linker
strh r0, [r5, #0xC]
bl linker
strh r0, [r5, #0xA]
ldr r1, =(0x2020000)
strh r0, [r1]
pop {r4-r5, pc}

linker:
bx r4


.align 2
rand:
.word (0x08044EC8 + 1)



Untested, and may not compile as is. Post updates here please.

Works well, thank you!

mbcn10ww May 10th, 2017 4:41 AM

Quote:

Originally Posted by FBI (Post 8547374)

Adjusting Shiny encounter chance



Pre-requisites:
- Shiny Pokemon Generator
- Random Number Generator


How to insert:

Before compiling the routine look at the last line. There is a .word 0x8[RANDOM +1]. Change the content after the 0x8 to be a pointer to where you inserted RANDOM +1.

Once you've done that, look for the line that says "mov r0, #0x1 @item ID". Change 0x1 to the Item ID for your Shiny charm item. If you don't have one implemented, delete these lines:
Code:

        mov r0, #0x1 @item ID
        mov r1, #0x1
        ldr r2, =(0x8099F40 +1)
        bl linker
        cmp r0, #0x0
        beq normal
        mov r0, #0xA
        lsl r0, r0, #0x7
        add r0, r0, #0x55 @1/1365 chance with shiny charm
        b calcChance


After you've done that, compile and insert the following routine into free space:

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r3}
        mov r0, #0x1 @item ID
        mov r1, #0x1
        ldr r2, =(0x8099F40 +1)
        bl linker
        cmp r0, #0x0
        beq normal
        mov r0, #0xA
        lsl r0, r0, #0x7
        add r0, r0, #0x55 @1/1365 chance with shiny charm
        b calcChance

normal:
        mov r0, #0x20
        lsl r0, r0, #0x7 @1/4096 chance normally

calcChance:
        ldr r1, =(0x20370B8)
        strh r0, [r1]
        ldr r2, .random
        bl linker
        cmp r0, #0xFF
        bne end
        ldr r1, =(0x20370BC)
        strh r0, [r1]
        ldr r1, =(0x20370B8)
        mov r0, #0x0
        strh r0, [r1]

end:
        pop {r0-r3}
        sub SP, SP, #0x20
        mov r7, r0
        ldr r4, [SP, #0x40]
        ldr r4, [SP, #0x48]
        mov r5, #0xE
        ldr r6, =(0x803DAD8 +1)
        bx r6

linker:
        bx r2

.align 2

.random:
        .word 0x8[RANDOM +1]




Now navigate to 0x3DACE and insert the following byte changes:
Code:

00 00 00 4F 38 47 XX XX XX 08


Where XX XX XX is the reverse hex pointer +1 to where you inserted this routine.


Usage:

It's Automagic, also happens to give the shiny chance to Pokemon in wild, trainer Pokemon, given Pokemon ect.

Right now encounter chance is 1/4096 without shiny charm, and 1/1356 with it.

There is a way to make it work only with wild and breeding and to make the shiny chance 1/2048?

tkim May 10th, 2017 1:18 PM

Quote:

Originally Posted by mbcn10ww (Post 9642663)
There is a way to make it work only with wild and breeding and to make the shiny chance 1/2048?

To make the shiny chance 1/2048 replace these lines
Code:

    mov r0, #0xA
    lsl r0, r0, #0x7
    add r0, r0, #0x55 @1/1365 chance with shiny charm


with
Code:

mov r0, #0x10
lsl r0, r0, #0x7


this is for when using the Shiny charm

mbcn10ww May 10th, 2017 1:55 PM

Quote:

Originally Posted by tkim (Post 9643011)
To make the shiny chance 1/2048 replace these lines
Code:

    mov r0, #0xA
    lsl r0, r0, #0x7
    add r0, r0, #0x55 @1/1365 chance with shiny charm


with
Code:

mov r0, #0x10
lsl r0, r0, #0x7


this is for when using the Shiny charm

Thank you so much.

Koople May 14th, 2017 10:30 AM

updated routine

AtecainCorp. May 16th, 2017 12:01 AM

Quote:

Originally Posted by Koople (Post 9647246)
Adding a Probability of Wild Pokemon Dodging Poke Balls (Fire Red)

This routine edits the pokeball throwing command to have a small chance (5-10%) of having the pokemon dodge your pokeball. The probability of missing is calculated by dividing the base speed of the wild pokemon by 10 and adding it to some initial threshold value. If a random value is less than or equal to this threshold, the ball misses.

The initial threshold value is 13 (0.05*255 ~= 13), and a high base speed pokemon (~130) will increase the threshold value to 26, so roughly 10% chance of missing. Of course, you can edit this formula as you see fit. I would also recommend editing the "It dodged the Poke Ball! It can't be caught!" text.

To use, insert this routine at 0xXXYYZZ and then insert 01 48 00 47 00 00 (ZZ+1) YY XX 08 at 0x0802D67A

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        ldr r1, .BallThrown
        ldrb r0, [r1]
        cmp r0, #0x5                                @safari ball ID
        beq SafariBall
        cmp r0, #0x1                                @master ball ID
        bne OtherBall
        ldr r0, =(0x03004F90)
        ldr r1, =(0x0802D688 +1)
        bx r1

SafariBall:
        ldr r0, =(0x0802D6BC +1)
        bx r0

OtherBall:
        ldr r0, .WildPoke
        mov r1, #0xB                        @species
        ldr r2, .GetAttr
        bl linker                                @r0 = species ID
        sub r0, r0, #0x1
        mov r1, #0x1C                                @pokedex data is 0x1C=28 bytes each
        mul r0, r0, r1
        ldr r1, .BaseStats
        add r0, r0, r1
        ldrb r0, [r1, #0x3]
        mov r1, #0xA
        bl div_func                                        @r0 =  base speed / 10 (integer value)
        mov r3, #0x0
        mov r1, #0xD
        add r3, r0, r1                                @r3 = threshold value = 13 + spd/10  (~5-10% chance of dodging)
        bl rand_func
        lsr r0, r0, #0x8
        cmp r0, r3
        bls DodgeBall
        ldr r0, =(0x0802D6A8 +1)        @else, continue with pokeball throw command
        bx r0

div_func:
        ldr r2, .Divide
        bx r2

rand_func:
        ldr r2, .Rand
        bx r2

DodgeBall:
        ldr r0, .Dodge        @pokemon dodges the pokeball - edit text so it doesn't say it cant be caught
        bx r0

linker:
        bx r2

.align 2
.BallThrown:        .word 0x02023D68
.GetAttr:        .word 0x0803FBE9        @get pokemon attribute r1 from address r0, store in r0
.Dodge:        .word 0x802D461                        @routine where pokemon dodges the pokeball (also edit the text itself (0x3FD6C7))
.Rand: .word 0x08044EC9                        @random bytes
.WildPoke:        .word 0x0202402C    @wild pokemon species ID
.BaseStats: .word 0x082547A0        @pokemon base stat data start (starts at 1, not 0!)
.Divide:        .word 0x081E4019        @divide r0 by r1, store integer result in r0



Wow... This code can be also usable for Emerald and Ruby users for make GHOST pokemon in the game possible. Just set aviod rate to 100% and GHOST was been unable to capture.

Urz May 16th, 2017 3:48 AM

Quote:

Originally Posted by Koople (Post 9647246)
Adding a Probability of Wild Pokemon Dodging Poke Balls (Fire Red)

This routine edits the pokeball throwing command to have a small chance (5-10%) of having the pokemon dodge your pokeball. The probability of missing is calculated by dividing the base speed of the wild pokemon by 10 and adding it to some initial threshold value. If a random value is less than or equal to this threshold, the ball misses.

The initial threshold value is 13 (0.05*255 ~= 13), and a high base speed pokemon (~130) will increase the threshold value to 26, so roughly 10% chance of missing. Of course, you can edit this formula as you see fit. I would also recommend editing the "It dodged the Poke Ball! It can't be caught!" text.

To use, insert this routine at 0xXXYYZZ and then insert 01 48 00 47 00 00 (ZZ+1) YY XX 08 at 0x0802D67A

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
    ldr r1, .BallThrown
    ldrb r0, [r1]
    cmp r0, #0x5                @safari ball ID
    beq SafariBall
    cmp r0, #0x1                @master ball ID
    bne OtherBall
    ldr r0, =(0x03004F90)
    ldr r1, =(0x0802D688 +1)
    bx r1

SafariBall:
    ldr r0, =(0x0802D6BC +1)
    bx r0

OtherBall:
    ldr r0, .WildPoke
    mov r1, #0xB            @species
    ldr r2, .GetAttr
    bl linker                @r0 = species ID
    sub r0, r0, #0x1
    mov r1, #0x1C                @pokedex data is 0x1C=28 bytes each
    mul r0, r0, r1
    ldr r1, .BaseStats
    add r0, r0, r1
    ldrb r0, [r1, #0x3]
    mov r1, #0xA
    bl div_func                    @r0 =  base speed / 10 (integer value)
    mov r3, #0x0
    mov r1, #0xD
    add r3, r0, r1                @r3 = threshold value = 13 + spd/10  (~5-10% chance of dodging)
    bl rand_func
    lsr r0, r0, #0x8
    cmp r0, r3
    bls DodgeBall
    ldr r0, =(0x0802D6A8 +1)    @else, continue with pokeball throw command
    bx r0

div_func:
    ldr r2, .Divide
    bx r2

rand_func:
    ldr r2, .Rand
    bx r2

DodgeBall:
    ldr r0, .Dodge    @pokemon dodges the pokeball - edit text so it doesn't say it cant be caught
    bx r0

linker:
    bx r2

.align 2
.BallThrown:    .word 0x02023D68
.GetAttr:    .word 0x0803FBE9    @get pokemon attribute r1 from address r0, store in r0
.Dodge:    .word 0x802D461            @routine where pokemon dodges the pokeball (also edit the text itself (0x3FD6C7))
.Rand: .word 0x08044EC9            @random bytes
.WildPoke:    .word 0x0202402C    @wild pokemon species ID
.BaseStats: .word 0x082547A0    @pokemon base stat data start (starts at 1, not 0!)
.Divide:    .word 0x081E4019    @divide r0 by r1, store integer result in r0



I've been testing this out a bit. One bug I've found is if your pokémon on the field has a status effect like sleep or paralysis, when you use a ball, the game will sometimes hang (presumably when the Pokémon 'dodges' the ball). Any reason for this you can figure out? If you poison or sleep the opponent, it works fine. It's just status effects to your Pokémon which are the problem

Otherwise, it works great :-)

Koople May 16th, 2017 8:03 AM

out of date, see updated post

tkim May 16th, 2017 9:12 AM

[FR]: Get IVs of a selected POKEMON in PARTY
Spoiler:
This routine reads the IVs of a selected POKEMON whose slot is stored at var 0x8004 and stores them at vars 0x8005-0x800A. It also stores the total amount of the IVs at var 0x8004.
Code:

.text
.align 2
.thumb
.thumb_func
.global getiv

main:
    push {r4-r7, lr}
    ldr r0, var8004        @slot number should be in var8004
    ldrh r0, [r0]
    mov r1, #0x64
    mul r1, r1, r0
    ldr r0, =(0x2024284) @partyram
    add r5, r1, r0        @slotram loaded
    mov r6, #0x27
    mov r1, r6
    ldr r0, var8004
    add r7, r0, #0x2 @var8005
    mov r4, #0x0

loop:
    mov r0, r5
    ldr r2, =(0x803FBE8|1) @getattr
    bl linker
    strh r0, [r7]            @store IVs into var8005-800A
    add r4, r4, r0
    add r6, r6, #0x1
    cmp r6, #0x2D
    beq exit
    mov r1, r6
    add r7, r7, #0x2
    b loop

exit:
    ldr r1, var8004
    strh r4, [r1]    @store total in var8004
    pop {r4-r7, pc}

linker:
    bx r2

.align 2
var8004:
    .word 0x20370C0


Example script:
Code:

#dynamic 0x800000
'---------------
#org @start
lock
faceplayer
special 0x9f
waitstate
callasm 0x8[routine offset+1]
buffernumber 0x0 0x8004
msgbox @IV MSG_KEEPOPEN '"[buffer1]"
release
end

'---------
' Strings
'---------
#org @IV
= [buffer1]



Squeetz May 18th, 2017 1:24 PM

Here's a short little routine for Firered that recalculates the entire party's stats because I wasn't sure if there was a similiar function.
Spoiler:
Code:

.thumb

.global recalcparty

setup:
        push {r4-r6, lr}
        mov r6, #0x0
        ldr r4, party_player
        ldr r5, poke_quantity
        ldrb r5, [r5]
        cmp r5, #0x0                @failsafe
        beq end
        sub r5, r5, #0x1        @zero-index it
loop:
        mov r1, #0x64
        mul r1, r6
        add r0, r4, r1
        ldr r3, recalcadr
        bl linker
        cmp r5, r6
        beq end
        add r6, r6, #0x1
        b loop

linker:
        bx r3

end:
        pop {r4-r6}
        pop {r1}
        bx r1

.align 2
        poke_quantity:        .word 0x02024029
        party_player:        .word 0x02024284
        recalcadr:        .word 0x0803E47C|1



EddyHg80 May 19th, 2017 12:49 AM

Feature request [EM][FR if you want]


A hacked giveitem command combined with showpokepic to achieve this:

http://i.imgur.com/3bqhTRs.png

(I made it with paint.net, it's not something I saw in a hack already)
PS. if possible the ideal thing would be that in a script you would only use the normal giveitem, so all the already existing scripts would get this feature

Spherical Ice May 19th, 2017 8:38 PM

[FR] Ability Capsule


Find 0x1FC bytes of free space at a word-aligned address, and take note of it.
Create an item of Type 1 ("Out of battle").
Set the item's Field pointer to the address you noted, plus 1.
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 0x1FC bytes.
Copy the bytes and paste them in your ROM, at the same address.

Code:

.thumb

.equ location, 0xXXXXXX
.equ rom, (0x08000000 + 1)

.equ ability_name_length, 0x0D
.equ base_stats_length, 0x1C
.equ pokemon_length,  0x64
.equ req_species, 0x0B
.equ req_species2, 0x41
.equ req_ability, 0x2E
.equ ability1, 0x16
.equ ability2, 0x17
.equ egg_species, 0x19C

.org location, 0xFF
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_species2
    ldr r3, get_attr
    bl call_via_r3

egg_check:
    ldrh r1, =egg_species
    cmp r0, r1
    beq fail

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:
    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_species2
    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, 0xB4, 0xE7, 0x00, 0xBB, 0xD6, 0xDD, 0xE0, 0xDD, 0xE8, 0xED, 0xFE, 0xD7, 0xDC, 0xD5, 0xE2, 0xDB, 0xD9, 0xD8, 0x00, 0xE8, 0xE3, 0x00, 0xFD, 0x03, 0xAB, 0xFC, 0x09, 0xFF
    @ "[PKMN]'s Ability[NEWLINE]changed to [ABILITY]![WAITKEYPRESS]"

.align 2
    fcode_buffer2:          .word 0x02021CD0
    fcode_buffer3:          .word 0x02021CF0
    displayed_string:      .word 0x02021D18
    party_player:          .word 0x02024284
    var_800D:              .word 0x020370D0
    var_800E:              .word 0x0203AD30
    brm:                    .word 0x0203B0A0
    item_effectiveness:    .word 0x0203B0C0

    tasks:                  .word 0x03005090
    item_function_ptr:      .word 0x03005E98

    base_stats_ptr:        .word 0x080001BC
    ability_names_ptr:      .word 0x080001C0
    strcpy_xFF_terminated:  .word 0x08008D84|1
    fdecoder:              .word 0x08008FCC|1
    get_attr:              .word 0x0803FBE8|1
    set_attr:              .word 0x0804037C|1
    audio_play:            .word 0x080722CC|1
    bag_remove_item:        .word 0x0809A1D8|1
    item_consume_maybe:    .word 0x080A16D0|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
    no_effect_str:          .word 0x084169DC @ "It won't have any effect."


This implementation is not identical to how it is in the official games, as it doesn't have a further prompt asking the player to confirm when a Pokémon is selected.

It will fail ("It won't have any effect") if used on a Pokémon whose base stats has two identical abilities, or if one of the abilities are ID 0x0.

EDIT 2019/05/29: There was a bug at line 72 where 0 was being stored at a garbage address. It also now checks the species using req_species2 to prevent the Ability Capsule (potentially) working on Eggs, and adds a relevant check (as it turns out, this is technically redundant as the Use menu will not come up for Eggs to begin with, but it's better to redundant than sorry). If you used this routine before this edit's date, I'd recommend updating the ASM to make sure! Thanks to BreadCrumbs/Squeetz for pointing these issues out!

Koople May 21st, 2017 5:31 PM

Probability of Dodging Poke Balls [FR]

This routine uses the wild pokemon's base speed stat to calculate a probability that it will dodge a thrown pokeball (~5-10%).

(credits to Urz, shanem7, and ghoulslash for bug finding, scripting, and testing!)

MAJOR EDITS:
1. Fixed bugs/battle flag checks for trainer battles/old man/poke dude, and ghost battles
2. Hook insertion changed to be more compatible with other battle routines
3. It adds in the ability to use a custom messages! So you can keep the original ghost battle string the same.
4. Added a check that makes the ball automatically miss if the enemy is in the air/underground/underwater (credit to shanem7 for this idea)
5. Changed it so the base threshold is halved for paralysis instead of an automatic contact
6. You can use the pokeball deflection animation instead of the pokemon dodging animation with your own custom message! See the comment in the code to see how
7. dodgeball rate modifiers based on evasion and speed stat changes
8. substitute causes auto-dodge
9. Wrap effect reduces dodge rate by 1/4 (added 8/5/17)
10. (9/28/18): fixed jump address to not overwrite register

NOTE: Safari Balls are unaffected by this routine. Master Ball is also unaffected but can be with an easy change (see comments)

Insertion:
*NOTE: THE HOOK ADDRESS HAS CHANGED TO 0802D508. REMEMBER TO RESTORE PREVIOUS HOOKS
Quote:

1. Insert custom 'dodging' message at 0xXXYYZZ (see below)
2. at 0x08XXXXXX: (Battle Script) Requires Jambo's setword battle command
Quote:

waitmessage 0x40
setword 0x203C020 0x08XXYYZZ @pointer to string 0xXXYYZZ you want to display (eg. "You missed wild [pkmn]!" or "Wild [pkmn] dodged your Poke Ball!")
printstring 0x184
waitmessage 0x40
end
3. Replace .Message :word 0x8XXXXXX with the offset you compiled this battle script in
4. Compile and insert the routine in free space (0xLLJJKK)
5. Insert 00 48 00 47 (KK+1) JJ LL 08 at 0802D508

The Routine:
Code:

Main:
        ldr r1, .BallThrown    @ remember to update RAM if you have expanded pokeballs!
        ldrb r0, [r1]
        cmp r0, #0x1                @master ball - move this check to the front of NoDodge to allow Master Ball to miss.
        bne OtherBall
        ldr r0, =(0x03004F90)
        ldr r1, =(0x0802D688 +1)
        bx r1

OtherBall:
        ldr r0, .SpecialStatus
        ldr r0, [r0]
        ldr r1, =(0x000400C0)
        and r0, r1
        cmp r0, #0x0
        bne DodgeBall        @auto-dodge if not on screen (fly/dive/dig/bounce)
        ldr r0, .TargetStatus
        ldrb r1, [r0, #0x7]
        mov r2, #0x1
        and r1, r2
        cmp r1, #0x1                @substitute on
        beq DodgeBall
        ldrb r0, [r0]
        cmp r0, #0x20
        beq NoDodge
        mov r1, #0x7
        and r0, r0, r1
        cmp r0, #0x0
        bne NoDodge

GetThreshold:
        ldr r0, .WildPoke
        mov r1, #0xB
        ldr r2, .GetAttr
        bl linker        @ r0 = target species ID
        mov r1, #0x1C
        mul r0, r1
        ldr r1, .BaseStats
        add r0, r0, r1
        ldrb r0, [r0, #0x3]  @ base speed
        mov r1, #0xA        @number to divide base speed by (change if you want)
        bl div_func
        mov r1, #0xD        @r1 = 13 (lower limit ~5% - change if you want)
        add r1, r0, r1

CheckParalysis:
        ldr r2, .TargetStatus
        ldrb r0, [r2]
        cmp r0, #0x40        @paralysis
        bne CheckWrap
        lsr r1, r1, #0x1        @if pokemon paralyzed, its dodge rate is halved

CheckWrap:
        add r2, r2, #0x4        @target status 2 bank
        ldrb r0, [r2, #0x1]
        mov r3, #0xE0
        and r0, r3
        cmp r0, #0x0
        beq CheckEvasion
@    beq CheckDodge      @use this jump if you don't want the Speed/Evasion stat change code
        lsr r2, r1, #0x2
        sub r1, r1, r2        @3/4 dodge rate if trapped by wrap effect
@ b CheckDodge      @use this jump if you don't want the Speed/Evasion stat change code

/*  evasion and speed modifiers    */

CheckEvasion:
        ldr r2, .TargetStatChanges
        ldrb r2, [r2, #0x7]
        cmp r2, #0x6
        bgt RaiseBase
        cmp r2, #0x6
        blt LowerBase
        b CheckSpeed

RaiseBase:
        sub r2, r2, #0x6
        lsl r2, r2, #0x2      @ add 4:4:24 for speed (1 through 5) -> lower limit=17(6%) to 37(14%)
        add r1, r1, r2
        b CheckSpeed

LowerBase:
        mov r3, #0x6
        sub r2, r3, r2
        lsl r2, r2, #0x1    @ lower limit=11/255(4%) to 1/255(.4%)
        cmp r1, r2
        blt NoDodge
        sub r1, r1, r2

CheckSpeed:
        ldr r2, .TargetStatChanges
        ldrb r2, [r2, #0x3]
        cmp r2, #0x6
        bgt RaiseBase2
        cmp r2, #0x6
        blt LowerBase2
        b CheckDodge

RaiseBase2:
        sub r2, r2, #0x6
        lsl r2, r2, #0x1      @r2 = 2:2:12
        add r1, r1, r2
        b CheckDodge

LowerBase2:
        mov r3, #0x6
        sub r2, r3, r2
        lsl r2, r2, #0x1
        cmp r1, r2
        blt NoDodge
        sub r1, r1, r2

/*  end of evasion and speed modifiers    */

CheckDodge:
        mov r3, r1
        bl rand_func
        lsr r0, r0, #0x8
        cmp r0, r3
        bls DodgeBall        @if r0 <= threshold, pokemon dodges

NoDodge:
        ldr r3, .BaseStats      @ remember to change if youve repointed!
        ldr r2, .BattleStruct
        ldrb r1, [r6]        @ target bank
        mov r0, #0x58
        ldr r5, =(0x0802D510 +1)        @return to original routine
        bx r5

div_func:
        ldr r2, .Divide
        bx r2

rand_func:
        ldr r2, .Rand
        bx r2

DodgeBall:
        mov r0, #0x0
        mov r1, #0x6          @change to mov r1, #0x5 for ball deflection animation
        ldr r2, =(0x0800E194 +1)
        bl linker
        ldrb r0, [r5]
        ldr r2, =(0x08017248 +1)
        bl linker
        ldr r1, =(0x02023D74)
        ldr r0, .DodgeMessage
        ldr r2, =(0x0802D7EC +1)
        bx r2

linker:
        bx r2

.align 2
.BallThrown:        .word 0x02023D68
.GetAttr:        .word 0x0803FBE9
.Rand: .word 0x08044EC9
.WildPoke:        .word 0x0202402C
.BaseStats: .word 0x08254784
.Divide:        .word 0x081E4019
.TargetStatus:        .word 0x02023C88
.BattleStruct:    .word 0x02023BE4
.TargetStatChanges:        .word 0x02023C54
.SpecialStatus:        .word 0x02023E00
.DodgeMessage:        .word 0x08XXXXXX        @custom 'dodgeball' battle script address. battle script must end in 0xF6


As always, please let me know if there are any bugs,you have any suggestions for the routine, or you need help inserting it.

Thanks :)

mbcn10ww May 22nd, 2017 8:52 AM

Quote:

Originally Posted by Koople (Post 9653926)
Update to this post:

Probability of Dodging Poke Balls [FR]

As mentioned in the original post, this routine uses the wild pokemon's base speed stat to calculate a probability that it will dodge a thrown pokeball (~5-10%). However, it would freeze the game if the user had a status condition.

Credits to Urz for helping substantially locate/solve the bizarre bug!

The updated routine (below), should remove the bug. I also added in a check that prevents the wild pokemon from dodging if it is asleep, frozen, or paralyzed, as is only logical :)

To use:
1. Insert routine at 0xXXYYZZ
2. Insert 01 48 00 47 00 00 (ZZ+1) YY XX 08 at 0x0802D452

Code:

.text
.align 2
.thumb
.thumb_func
.global dodgeball

main:
        ldr r1, .BallThrown
        ldrb r0, [r1]
        cmp r0, #0x5                                @safari ball ID
        beq SafariBall
        cmp r0, #0x1                                @master ball ID
        bne OtherBall
        ldr r0, =(0x03004F90)
        ldr r1, =(0x0802D688 +1)
        bx r1

SafariBall:
        ldr r0, =(0x0802D6BC +1)
        bx r0

OtherBall:
        ldr r0, .TargetStatus
        ldrb r0, [r0]
        cmp r0, #0x40                @paralysis
        beq NoDodge
        cmp r0, #0x20
        beq NoDodge                        @frozen
        mov r1, #0x7
        and r0, r0, r1                @sleep (between 0x1 and 0x5)
        cmp r0, #0x0
        bne NoDodge

CheckThreshold:
        ldr r0, .WildPoke
        mov r1, #0xB
        ldr r2, .GetAttr                        @get species ID of wild pokemon
        bl linker
        sub r0, r0, #0x1
        mov r1, #0x1C                                @pokedex data is 0x1C=28 bytes each
        mul r0, r0, r1
        ldr r1, .BaseStats
        add r0, r0, r1
        ldrb r0, [r0, #0x3]                        @r0 = wild pokemon base speed
        mov r1, #0xA
        bl div_func                                        @r0 =  base speed / 10 (change if you want)
        mov r3, #0x0
        mov r1, #0xD                                @r1 = 13, lower limit (change if you want)
        add r3, r0, r1                                @r3 = 13 + base_speed/10 = threshold to compare against random byte (~5-10%)
        bl rand_func
        lsr r0, r0, #0x8                        @r0 = random byte
        cmp r0, r3
        bls DodgeBall                                @if r0 <= threshold value, the pokemon dodges the ball

NoDodge:
        ldr r0, =(0x0802D4B4 +1)        @continue with pokemon throw command
        bx r0

div_func:
        ldr r2, .Divide
        bx r2

rand_func:
        ldr r2, .Rand
        bx r2

DodgeBall:
        ldr r0, .Dodge                        @pokemon dodges the pokeball - edit text so it doesn't say it can't be caught
        bx r0

linker:
        bx r2

.align 2
.BallThrown:        .word 0x02023D68
.GetAttr:        .word 0x0803FBE9        @get pokemon attribute r1 from address r0, store in r0
.Dodge:        .word 0x802D461                        @routine where pokemon dodges the pokeball (also edit the text itself (0x3FD6C7))
.Rand: .word 0x08044EC9                        @random bytes
.WildPoke:        .word 0x0202402C    @wild pokemon species ID
.BaseStats: .word 0x082547A0        @pokemon base stat data start (starts at 1, not 0!)
.Divide:        .word 0x081E4019        @divide r0 by r1, store integer result in r0
.TargetStatus:        .word 0x02023C88        @target status bank


EDIT: of course, please let me know if there are any more bugs.

One question, the hook at the old post is at 0x2D67A and this one is at 0x2D452, the system will need the two routines or I can restore the vanilla data in the old post's hook offset? Or you mistakenly used the wrong hook? (The offset in question is for the hook of uncapturable Pokémon)

Koople May 22nd, 2017 10:23 AM

Quote:

Originally Posted by mbcn10ww (Post 9654457)
One question, the hook at the old post is at 0x2D67A and this one is at 0x2D452, the system will need the two routines or I can restore the vanilla data in the old post's hook offset? Or you mistakenly used the wrong hook? (The offset in question is for the hook of uncapturable Pokémon)

Sorry, I should have specified. You will need to restore the data at 0x0802D67A and instead insert the hook at 0x082D452. And then replace 0x0802D6A8+1 with 0x0802D4B4+1 as in the updated routine.

Spherical Ice May 22nd, 2017 2:07 PM

Please give your feedback to potential changes for this thread at this thread: https://www.pokecommunity.com/showthread.php?t=393085


All times are GMT -8. The time now is 8:46 AM.


Like our Facebook Page Follow us on Twitter © 2002 - 2018 The PokéCommunity™, pokecommunity.com.
Pokémon characters and images belong to The Pokémon Company International and Nintendo. This website is in no way affiliated with or endorsed by Nintendo, Creatures, GAMEFREAK, The Pokémon Company or The Pokémon Company International. We just love Pokémon.
All forum styles, their images (unless noted otherwise) and site designs are © 2002 - 2016 The PokéCommunity / PokéCommunity.com.
PokéCommunity™ is a trademark of The PokéCommunity. All rights reserved. Sponsor advertisements do not imply our endorsement of that product or service. User generated content remains the property of its creator.

Acknowledgements
Use of PokéCommunity Assets
vB Optimise by DragonByte Technologies Ltd © 2023.