• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Our weekly protagonist poll is now up! Vote for your favorite Conquest protagonist in the poll by clicking here.
  • 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

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
 
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.
 
Last edited:
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:

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

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 :-)
 
Last edited:
[FR]: Get IVs of a selected POKEMON in PARTY
Spoiler:
 
Last edited:
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:
 
Feature request [EM][FR if you want]

A hacked giveitem command combined with showpokepic to achieve this:

[PokeCommunity.com] ASM Resource Thread


(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
 

[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:
[FONT="Source Code Pro"].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."

[/FONT]

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!
 
Last edited:
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
1. Insert custom 'dodging' message at 0xXXYYZZ (see below)
2. at 0x08XXXXXX: (Battle Script) Requires Jambo's setword battle command
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 :)
 
Last edited:
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)
 
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.
 
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.

But the old offset cannot be used instead? Because some people like me uses this offset for hooking the Uncapturable Pok?mon system.
 
IDEA
I'm trying to add a feature that I'm sure it's possible to do. It consist on showing the real time as a clock do (I inserted RTC system) in the start menu, so in fact, the only thing to do is to display in the start menu a box with text that will be the hour based on the statusbytes located in the specified RAM offset.
 
But the old offset cannot be used instead? Because some people like me uses this offset for hooking the Uncapturable Pok?mon system.

Ah, I see what you mean. Well, I haven't tested it myself, but I imagine even with updating the NoDodge routine to 0x0802D4B4 +1, inserting at the old hook would not get rid of the bug that freezes the game when there's a status condition.

I would suggest merging the two routines; anytime before the NoDodge snippet (at the beginning of OtherBall is probably best), just add in:
Code:
ldr r2, .VAR
ldrb r2, [r2]
cmp r2, #0x1
beq DodgeBall

And that should make it so if your variable is toggled on, the pokemon automatically dodges the ball.

EDIT: I edited the post to reflect these changes, as well. Thanks for letting me know about that conflict :)
EDIT 2: I forgot about the master ball - You should be able to just add those four lines above to the beginning of the routine if you want all Pokeballs to miss.
 
Last edited:
Ah, I see what you mean. Well, I haven't tested it myself, but I imagine even with updating the NoDodge routine to 0x0802D4B4 +1, inserting at the old hook would not get rid of the bug that freezes the game when there's a status condition.

I would suggest merging the two routines; anytime before the NoDodge snippet (at the beginning of OtherBall is probably best), just add in:
Code:
ldr r2, .VAR
ldrb r2, [r2]
cmp r2, #0x1
beq DodgeBall

And that should make it so if your variable is toggled on, the pokemon automatically dodges the ball.

EDIT: I edited the post to reflect these changes, as well. Thanks for letting me know about that conflict :)
EDIT 2: I forgot about the master ball - You should be able to just add those four lines above to the beginning of the routine if you want all Pokeballs to miss.

My version of the Uncapturable Pok?mon routine have a flag instead of variable, but it worked fine. ^^

EDIT: I don't know if you tested, but your updated routine now makes all wild pkmn always dodge.
 
Last edited:
My version of the Uncapturable Pok?mon routine have a flag instead of variable, but it worked fine. ^^

EDIT: I don't know if you tested, but your updated routine now makes all wild pkmn always dodge.

I had tested it before adding in the capturability toggle and there were no issues
 
Please look at following words if you want the custom moves!!!
Firstly to use custom moves you need a routine written by FBI and modified by me which was originally posted here:

Custom 'givepokemon'

No bugs found in this hack.
Code:
.thumb
/*EWRAM:020370B8 var_8000: species      
EWRAM:020370BA var_8001: level      
EWRAM:020370BC var_8002: held item      
EWRAM:020370BE var_8003: attack 1     
EWRAM:020370C0 var_8004: attack 2      
EWRAM:020370C2 var_8005: attack 3      
EWRAM:020370C4 var_8006: attack 4      
EWRAM:020370C6 var_8007: HP IV      
EWRAM:020370C8 var_8008: attack IV     
EWRAM:020370CA var_8009: defence IV      
EWRAM:020370CC var_800A: speed IV      
EWRAM:020370CE var_800B: sp. attack IV      
EWRAM:020370D0 var_800D: sp. defence IV      
EWRAM:020370D2 var_800F: shiny?
EWRAM:020370DE var_8014: ball*/

main_func:
push {r4-r7, lr}
sub sp, sp, #0x20
mov r0, #0x64
ldr r1, .malloc
bl jump_r1
mov r8, r0
ldr r1, .clear
bl jump_r1
mov r0, r8
ldr r1, .clear2
bl jump_r1
ldr r1, .random
bl jump_r1
mov r4, r0
ldr r0, .saveblockptr
ldr r2, [r0]
add r2, #0xA @OTID_loc
add r6, r2, #0
ldrh r1, [r2]
ldrh r5, [r2, #2]
eor r5, r1 @TID xor SID
ldr r3, .var
ldrh r3, [r3, #0x1A]
ldr r1, .random
bl jump_r1
bl shinycheck
/*r0 = PID1, r4 = PID2*/
lsl r0, r0, #0x10
ldr r2, .var
add r2, #0x20
strh r4, [r2]
orr r0, r4 @PID
mov r1, #0
ldr r2, .var
add r2, #0x1C
str r0, [r2]
mov r0, r8
ldr r3, .setter1
bl jump_r3
mov r0, r8
ldr r3, .setter1
mov r1, #1
add r2, r6, #0
bl jump_r3
mov r0, r8
ldr r1, .checksum
bl jump_r1
ldr r2, .var
add r2, #0x1C
strh r0, [r2]
mov r0, r8
mov r1, #9
ldr r3, .setter1
bl jump_r3
mov r0, r8
ldr r1, .encrypt
bl jump_r1
mov r0, sp
ldr r1, .var
ldrh r1, [r1]
ldr r3, .loadname
bl jump_r3
mov r0, r8
mov r1, #2
mov r2, sp
ldr r3, .setter1
bl jump_r3
ldr r2, .language
mov r0, r8
mov r1, #3
ldr r3, .setter1
bl jump_r3
mov r0, r8
ldr r5, .saveblockptr
ldr r2, [r5]
mov r1, #7
ldr r3, .setter1
bl jump_r3
mov r0, r8
mov r1, #0xb
ldr r2, .var
ldr r3, .setter1
bl jump_r3
ldr r4, .stat
ldr r2, .var
ldrh r1, [r2]
lsl r0, r1, #3
sub r0, r0, r1
lsl r0, r0, #2
add r0, r0, r4
ldrb r1, [r0, #0x13] 
mov r0, #0xCA
lsl r0, r0, #1
add r2, r1, #0
mul r2, r0
ldr r0, .var
ldrb r0, [r0, #2]
lsl r0, r0, #2
ldr r1, .exp
add r0, r0, r1
add r2, r2, r0
mov r0, r8
mov r1, #0x19
ldr r3, .setter1
bl jump_r3
ldr r1, .var
ldrh r0, [r1]
lsl r2, r0, #3
sub r2, r2, r0
lsl r2, r2, #2
add r4, #0x12
add r2, r2, r4
mov r0, r8
mov r1, #0x20
ldr r3, .setter1
bl jump_r3
ldr r1, .catchlocation
bl jump_r1
lsl r0, r0, #0x18
lsr r0, r0, #0x18
mov r1, #0x23
ldr r2, .var
add r2, #0x1C
str r0, [r2]
mov r0, r8
ldr r3, .setter1
bl jump_r3
mov r0, r8
mov r1, #0x24
ldr r2, .var
add r2, r2, #2
ldr r3, .setter1
bl jump_r3
mov r0, r8
ldr r2, .version
mov r1, #0x25
ldr r3, .setter1
bl jump_r3
ldr r2, .var
add r2, #0x26
mov r1, #0x26
mov r0, r8
ldr r3, .setter1
bl jump_r3
ldr r2, [r5]
add r2, #8
mov r0, r8
mov r1, #0x31
ldr r3, .setter1
bl jump_r3
bl iv_encrypt
ldr r2, .stat
ldr r3, .var
ldrh r1, [r3]
lsl r0, r1, #3
sub r0, r0, r1
lsl r0, r0, #2
add r0, r0, r2
ldrb r0, [r0, #0x17]
cmp r0, #0
beq end
ldr r2, .var
add r2, #0x1C
ldrh r0, [r2, #4]
mov r1, #1
and r0, r1
str r0, [r2]
mov r0, r8
mov r1, #0x2E
ldr r3, .setter1
bl jump_r3

end:
mov r0, r8
ldr r1, .sub_803E9E0
bl jump_r1
mov r0, r8
mov r1, #0x38
ldr r2, .var
add r2, r2, #2
ldr r3, .setter2
bl jump_r3
mov r0, r8
mov r1, #0x40
ldr r2, .var
add r2, #0x1C
mov r3, #0xFF
str r3, [r2]
ldr r3, .setter2
bl jump_r3
mov r0, r8
ldr r1, .recalculation
bl jump_r1
mov r0, r8
mov r1, #0xC
ldr r2, .var
add r2, #4
ldr r3, .setter2
bl jump_r3
mov r0, r8
ldr r1, .catch
bl jump_r1
lsl r0, r0, #0x18
lsr r4, r0, #0x18
ldr r0, .var
ldrh r0, [r0]
ldr r1, .convert
bl jump_r1
lsl r0, r0, #0x10
lsr r5, r0, #0x10
cmp r4, #1
bgt back
cmp r4, #0
blt back
add r0, r5, #0
mov r1, #2
ldr r3, .dexcheck
bl jump_r3
add r0, r5, #0
mov r1, #3
ldr r3, .dexcheck
bl jump_r3

back:
mov r0, r8
ldr r1, .free
bl jump_r1
add r0, r4, #0
ldr r4, .var
strh r0, [r4, #0x18]
add sp, sp, #0x20
mov r0, #0
pop {r4-r7, pc}

shinycheck:
push {lr}
cmp r3, #0
beq jump_pc
ldr r1, .random
bl jump_r1
mov r1, #7
and r0, r1
eor r0, r5
eor r0, r4

jump_pc:
pop {pc}

iv_encrypt:
push {lr}
mov r7, #0
loop_iv:
ldr r2, .var
add r2, #0xE
mov r0, r8
ldr r3, .setter1
add r1, r7, #0
add r1, #0x27
lsl r6, r7, #1
add r2, r2, r6
bl jump_r3
add r7, r7, #1
cmp r7, #6
bne loop_iv
pop {pc}

jump_r1:
bx r1

jump_r3:
bx r3

.align 2
.malloc: .word 0x08002BB1
.clear: .word 0x0803D995
.clear2: .word 0x0803D97D
.random: .word 0x8044EC9
.setter1: .word 0x080404D1
.saveblockptr: .word 0x300500C
.var: .word 0x020370B8
.checksum: .word 0x0803E3E9
.encrypt: .word 0x0803F8F9
.loadname: .word 0x08040FD1
.language: .word 0x081E9F11
.stat: .word 0x08254784
.exp: .word 0x08253AE4
.catchlocation: .word 0x08056261
.version: .word 0x081E9F10
.sub_803E9E0: .word 0x0803E9E1
.setter2: .word 0x0804037D
.recalculation: .word 0x0803E47D
.catch: .word 0x08040B15
.convert: .word 0x08043299
.dexcheck: .word 0x08088E75
.free: .word 0x08002BC5

Usage: (script)
Code:
lock
faceplayer
setvar 0x40ff 0x1 //custom move trigger
setvar 0x8000 0x19A //species
setvar 0x8001 0x28 //level
setvar 0x8002 0x8F //item
setvar 0x8003 0x1 //moves
setvar 0x8004 0x2
setvar 0x8005 0x3
setvar 0x8006 0x4
setvar 0x8007 0x1B //IVs
setvar 0x8008 0x1C
setvar 0x8009 0x1D
setvar 0x800A 0x1E
setvar 0x800B 0x1F
setvar 0x800D 0x1F
setvar 0x800F 0x1 //shiny
setvar 0x8014 0x4 //pokeball
callasm 0x8LLLLLL //offset of the function + 1
setvar 0x40ff 0x0 //make it normal
release
end

Custom 'setwildbattle'

along with a question
I've also developed a routine which can customize the wild pokemon for firered.
Insert this piece of code in free space:
Code:
.thumb
/*EWRAM:020370B8 var_8000: species      
EWRAM:020370BA var_8001: level      
EWRAM:020370BC var_8002: held item      
EWRAM:020370BE var_8003: attack 1     
EWRAM:020370C0 var_8004: attack 2      
EWRAM:020370C2 var_8005: attack 3      
EWRAM:020370C4 var_8006: attack 4      
EWRAM:020370C6 var_8007: HP IV      
EWRAM:020370C8 var_8008: attack IV     
EWRAM:020370CA var_8009: defence IV      
EWRAM:020370CC var_800A: speed IV      
EWRAM:020370CE var_800B: sp. attack IV      
EWRAM:020370D0 var_800D: sp. defence IV      
EWRAM:020370D2 var_800F: shiny?*/

main_func:
push {r4-r7, lr}
sub sp, sp, #0x20
ldr r1, .clear
bl jump_r1
ldr r0, .pkmndata
ldr r1, .clear2
bl jump_r1
ldr r1, .random
bl jump_r1
mov r4, r0
ldr r0, .saveblockptr
ldr r2, [r0]
add r2, #0xA @OTID_loc
add r6, r2, #0
ldrh r1, [r2]
ldrh r5, [r2, #2]
eor r5, r1 @TID xor SID
ldr r3, .var
ldrh r3, [r3, #0x1A]
ldr r1, .random
bl jump_r1
bl shinycheck
/*r0 = PID1, r4 = PID2*/
lsl r0, r0, #0x10
ldr r2, .var
add r2, #0x20
strh r4, [r2]
orr r0, r4 @PID
mov r1, #0
ldr r2, .var
add r2, #0x1C
str r0, [r2]
ldr r0, .pkmndata
ldr r3, .setter1
bl jump_r3
ldr r0, .pkmndata
ldr r3, .setter1
mov r1, #1
add r2, r6, #0
bl jump_r3
ldr r0, .pkmndata
ldr r1, .checksum
bl jump_r1
ldr r2, .var
add r2, #0x1C
strh r0, [r2]
ldr r0, .pkmndata
mov r1, #9
ldr r3, .setter1
bl jump_r3
ldr r0, .pkmndata
ldr r1, .encrypt
bl jump_r1
mov r0, sp
ldr r1, .var
ldrh r1, [r1]
ldr r3, .loadname
bl jump_r3
ldr r0, .pkmndata
mov r1, #2
mov r2, sp
ldr r3, .setter1
bl jump_r3
ldr r2, .language
ldr r0, .pkmndata
mov r1, #3
ldr r3, .setter1
bl jump_r3
ldr r0, .pkmndata
ldr r5, .saveblockptr
ldr r2, [r5]
mov r1, #7
ldr r3, .setter1
bl jump_r3
ldr r0, .pkmndata
mov r1, #0xb
ldr r2, .var
ldr r3, .setter1
bl jump_r3
ldr r4, .stat
ldr r2, .var
ldrh r1, [r2]
lsl r0, r1, #3
sub r0, r0, r1
lsl r0, r0, #2
add r0, r0, r4
ldrb r1, [r0, #0x13] 
mov r0, #0xCA
lsl r0, r0, #1
add r2, r1, #0
mul r2, r0
ldr r0, .var
ldrb r0, [r0, #2]
lsl r0, r0, #2
ldr r1, .exp
add r0, r0, r1
add r2, r2, r0
ldr r0, .pkmndata
mov r1, #0x19
ldr r3, .setter1
bl jump_r3
ldr r1, .var
ldrh r0, [r1]
lsl r2, r0, #3
sub r2, r2, r0
lsl r2, r2, #2
add r4, #0x12
add r2, r2, r4
ldr r0, .pkmndata
mov r1, #0x20
ldr r3, .setter1
bl jump_r3
ldr r1, .catchlocation
bl jump_r1
lsl r0, r0, #0x18
lsr r0, r0, #0x18
mov r1, #0x23
ldr r2, .var
add r2, #0x1C
str r0, [r2]
ldr r0, .pkmndata
ldr r3, .setter1
bl jump_r3
ldr r0, .pkmndata
mov r1, #0x24
ldr r2, .var
add r2, r2, #2
ldr r3, .setter1
bl jump_r3
ldr r0, .pkmndata
ldr r2, .version
mov r1, #0x25
ldr r3, .setter1
bl jump_r3
mov r0, #4
ldr r2, .var
add r2, #0x1C
str r0, [r2]
mov r1, #0x26
ldr r0, .pkmndata
ldr r3, .setter1
bl jump_r3
ldr r2, [r5]
add r2, #8
ldr r0, .pkmndata
mov r1, #0x31
ldr r3, .setter1
bl jump_r3
bl iv_encrypt
ldr r2, .stat
ldr r3, .var
ldrh r1, [r3]
lsl r0, r1, #3
sub r0, r0, r1
lsl r0, r0, #2
add r0, r0, r2
ldrb r0, [r0, #0x17]
cmp r0, #0
beq end
ldr r2, .var
add r2, #0x1C
ldrh r0, [r2, #4]
mov r1, #1
and r0, r1
str r0, [r2]
ldr r0, .pkmndata
mov r1, #0x2E
ldr r3, .setter1
bl jump_r3

end:
ldr r0, .pkmndata
ldr r1, .sub_803E9E0
bl jump_r1
ldr r0, .pkmndata
mov r1, #0x38
ldr r2, .var
add r2, r2, #2
ldr r3, .setter2
bl jump_r3
ldr r0, .pkmndata
mov r1, #0x40
ldr r2, .var
add r2, #0x1C
mov r3, #0xFF
str r3, [r2]
ldr r3, .setter2
bl jump_r3
ldr r0, .pkmndata
ldr r1, .recalculation
bl jump_r1
ldr r0, .pkmndata
mov r1, #0xC
ldr r2, .var
add r2, #4
ldr r3, .setter2
bl jump_r3
add sp, sp, #0x20
mov r0, #0
pop {r4-r7, pc}

shinycheck:
push {lr}
cmp r3, #0
beq jump_pc
ldr r1, .random
bl jump_r1
mov r1, #7
and r0, r1
eor r0, r5
eor r0, r4

jump_pc:
pop {pc}

iv_encrypt:
push {lr}
mov r7, #0
loop_iv:
ldr r2, .var
add r2, #0xE
ldr r0, .pkmndata
ldr r3, .setter1
add r1, r7, #0
add r1, #0x27
lsl r6, r7, #1
add r2, r2, r6
bl jump_r3
add r7, r7, #1
cmp r7, #6
bne loop_iv
pop {pc}

jump_r1:
bx r1

jump_r3:
bx r3

.align 2
.clear: .word 0x0803DA35
.pkmndata: .word 0x0202402C
.clear2: .word 0x0803D97D
.random: .word 0x8044EC9
.setter1: .word 0x080404D1
.saveblockptr: .word 0x300500C
.var: .word 0x020370B8
.checksum: .word 0x0803E3E9
.encrypt: .word 0x0803F8F9
.loadname: .word 0x08040FD1
.language: .word 0x081E9F11
.stat: .word 0x08254784
.exp: .word 0x08253AE4
.catchlocation: .word 0x08056261
.version: .word 0x081E9F10
.sub_803E9E0: .word 0x0803E9E1
.setter2: .word 0x0804037D
.recalculation: .word 0x0803E47D

How to use:
Create a script: (The usage of the variables are listed in the comment of the function written by me)
Code:
lock
faceplayer
setvar 0x40ff 0x1 //custom move trigger
setvar 0x8000 0x19A //species
setvar 0x8001 0x28 //level
setvar 0x8002 0x8F //item (This won't work, so you can't make the pokemon hold an item because another routine clears it. I don't know the reason and I can only wait for fixing. )
setvar 0x8003 0x1 //moves
setvar 0x8004 0x2
setvar 0x8005 0x3
setvar 0x8006 0x4
setvar 0x8007 0x1F //max IVs
setvar 0x8008 0x1F
setvar 0x8009 0x1F
setvar 0x800A 0x1F
setvar 0x800B 0x1F
setvar 0x800D 0x1F
setvar 0x800F 0x1 //shiny
callasm 0x8MMMMMM //offset of the ASM function +1
dowildbattle
setvar 0x40ff 0x0 //make it normal
release
//Here you can insert other codes. 
end

The item will be cleared by another routine (around 0x44446), so I hope that someone can fix the bug to make the routine more perfect. :)


I encountered a bug on custom give pokemon.

If the specie number is 5, the level of the pokemon will also be 5 no matter what the value you put in var 0x8001.


Okay, the real problem here is if your specie number is greater than 411 then the level of the pokemon you get is not correct.

EDIT: I have extended Pokemon. I'm using pokefreak890's base

EDITEDIT: I found the fix

Code:
.language: .word 0x081E9F11
.stat: .word 0x08254784    Change this to the location where your Pokemon Data is.
.exp: .word 0x08253AE4

I don't know if there are other stuffs that needs to be change. You only need to do this if you have extended the number of Pokemon in you rom.

EDITEDITEDIT: For some reason there are still problems to some Pokemon.

Sometimes you get Level 0, sometimes 100, sometimes 58.
I hope someone can fix this.


 
Last edited:
Back
Top