• 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

19
Posts
7
Years
  • Age 28
  • Seen Apr 14, 2017
Good job :). I was pretty lazy back then and just duplicated the font functions :D.

Seems you're quite proficient in ASM. Wonder if you use IDE?

Thanks! Did you mean to ask if I use IDA? If so, yes. Been using it for years now, mainly with Android OS development (patching old closed-source libs to work on newer Android versions for example). This is my first time writing any substantial assembly though, just so happens that reading assembly the past few years translated well into writing it.

In a way, ARM assembly is really not that different from programming in high-level languages like C. I just look at all the opcodes like functions, registers are variables, etc. Just takes more steps to do a particular task.

I've also made use of the no$gba debugger, that's how I find tricks to save instructions, like r0 containing a return address and the usage of r9 to determine which code to run for the stat coloring merger.

Sorry, I tend to ramble on and talk a lot. :p
 
794
Posts
10
Years
Thanks! Did you mean to ask if I use IDA? If so, yes. Been using it for years now, mainly with Android OS development (patching old closed-source libs to work on newer Android versions for example). This is my first time writing any substantial assembly though, just so happens that reading assembly the past few years translated well into writing it.

In a way, ARM assembly is really not that different from programming in high-level languages like C. I just look at all the opcodes like functions, registers are variables, etc. Just takes more steps to do a particular task.

I've also made use of the no$gba debugger, that's how I find tricks to save instructions, like r0 containing a return address and the usage of r9 to determine which code to run for the stat coloring merger.

Sorry, I tend to ramble on and talk a lot. :p

Yeah I meant IDA, lol. I asked, because I've got an up-to-date Emerald IDB. I know Touched has one in its signature, but it has less stuff labeled. Here's the link: https://www.dropbox.com/s/mksltpeelzj1tmi/BPEE_updated2.idb?dl=0

And yeah I use no$gba debugger too, a pretty handy tool.
 
352
Posts
7
Years
  • Age 30
  • Seen Mar 10, 2022
Made another improvement to the reusable pokeballs: safari balls can now be reused as well!

Code:
.text
.align 2
.thumb

@ FE3AA - 00 21
@ 56818 - 00 48 00 47 XX+1 XX XX XX
@ 3F008 - 02 E0 C0 46 C0 46 C0 46 [B][COLOR="Red"]! NEW[/COLOR][/B]
@ Optional: change initial safari ball count?: FC0E6 - XX 20, XX = initial count

main:
	@ if safari ball counter is not 0, then that's what we need to delete
	ldr r1, .safari_ball_count
	ldrb r0, [r1]
	cmp r0, #0x0
	bne delete_safari_ball
	
	@ ...otherwise, delete the last used item (if it's a pokeball)
	ldr r0, .last_used_item
	ldrh r0, [r0]
	@ checks that the item id is premier ball or lower
	cmp r0, #0xC
	bls delete_ball_in_bag
	@ support for custom pokeballs can be added like so:
	@ cmp r0, #CUSTOM_BALL_ID
	@ beq delete_ball_in_bag
	
	b finish


delete_safari_ball:
	@ r0 already contains current safari ball count, and
	@ r1 already contains safari ball count memory address
	sub r0, #1
	strb r0, [r1]
	b finish


delete_ball_in_bag:
	@ r0 already contains last_used_item.
	mov r1, #1
	ldr r2, .bag_remove_item
	bl x_r2
	b finish


finish:
	mov r9, r4
	mov r10, r5
	pop {r4-r7}
	pop {r2}
x_r2:
	bx r2


.align 2
.last_used_item:
	.word 0x0203CE7C
.bag_remove_item:
	.word 0x080D6AA4|1
.safari_ball_count:
	.word 0x0203A04C

Ported to Fire Red

Code:
.text
.align 2
.thumb

[COLOR="red"]@ 0xA1E30 - 00 21
@ 0x2D924 - 00 48 00 47 XX+1 XX XX 08
@ 0x16AD8 - 02 E0 C0 46 C0 46 C0 46
@ Optional: change initial safari ball count?: 0xA0ED2 - XX 20, XX = initial count[/COLOR]
main:
	@ if safari ball counter is not 0, then that's what we need to delete
	ldr r1, .safari_ball_count
	ldrb r0, [r1]
	cmp r0, #0x0
	bne delete_safari_ball
	
	@ ...otherwise, delete the last used item (if it's a pokeball)
	ldr r0, .last_used_item
	ldrh r0, [r0]
	@ checks that the item id is premier ball or lower
	cmp r0, #0xC
	bls delete_ball_in_bag
	@ support for custom pokeballs can be added like so:
	@ cmp r0, #CUSTOM_BALL_ID
	@ beq delete_ball_in_bag
	
	b finish


delete_safari_ball:
	@ r0 already contains current safari ball count, and
	@ r1 already contains safari ball count memory address
	sub r0, #1
	strb r0, [r1]
	b finish


delete_ball_in_bag:
	@ r0 already contains last_used_item.
	mov r1, #1
	ldr r2, .bag_remove_item
	bl x_r2
	b finish

x_r2:
	bx r2


finish:
	mov r9, r4
	mov r10, r5
	pop {r4-r7}
	pop {r0}
	bx r0

.align 2
[COLOR="red"].last_used_item:
	.word 0x0203AD30
.bag_remove_item:
	.word 0x0809A1D8|1
.safari_ball_count:
	.word 0x02039994[/COLOR]
 

ASDBUDDY

The Derp
347
Posts
7
Years
I think he wants to set a default name while skipping the intro. If you skip the intro via ASM, the default name is left as 0s aka blank.

Setting a static name to the player


Well, this is beyond simple, lol. I'll keep my post the same format though, because first post :3

How to insert:

Before you begin to insert the routine, there are a few steps. Firstly player names are limited to 8 characters with the eighth character = 0xFF.
Convert the static name you want from ascii to hex. For OP, he wanted Jesse and James which convert into:
C4 D9 E7 E7 D9 FF FF FF - Jesse
C4 D5 E1 D9 E7 FF FF FF -James
Note that if all eight bytes don't get used, you should pad them with "FF" in your hex editor.
Now insert the 8 byte names into some free space in your ROM via hex editor and write down the pointers.

Now copy the following routine into a text editor:
Spoiler:


You'll notice that I have the lines:
Code:
.CustomNameBoy:
	.word 0x@pointer to boy name

.CustomNameGirl:
	.word 0x@pointer to girl name

Change the 0x@pointer text to 0x[offset you inserted]. No need to add one.
After you've done that compile and insert into free space.

Usage:
You must callasm to the routine, and depending on the Player's gender it will set their name. To have their name inserted before the player starts playing the game, create a level script which calls this routine. If you don't know how, ask in a relevant thread (not here).

Hi, well I did exactly what you said but now my gba file just shows a blank screen when loaded into the emulator. What should I do?
 
100
Posts
7
Years
Hey, IDK if it is possible, but could it be made so the battle text auto-advances when in battle (like Gen 4)?

So, instead of being required to press A during certain parts (example: challenge, faint, disable, level up, etc), after 1 second, the next line will load. But you can interrupt it with A as well

I can make it automatically skip by editing the hex, but it does it immediately.
 
146
Posts
11
Years
  • CO
  • Seen Mar 16, 2023

Pokemon Storage (outside the PC)


Basically, in it's current state, this is effectively a storage system. It stores Pokemon and can be interacted with by the player to withdraw or deposit Pokemon. It's standalone from the PC storage system and is also much smaller (I've limited it to 6, but it can go upto 47). Some things that you will be able to do with this routine (and conjunction with some smaller ones) include:
- Extra Pokemon storage, you can possibly get a little over 1 box worth
- Flash back battles (complete swap between stored Pokemon and party Pokemon with capabilities to swap back)
- Carry a party of greater than 6 Pokemon (you can use the 2nd party for HM slaves, or whatever)
- Trade evolver guy! He will take your Pokemon and then when you come back it can be evolved! (silent evolution ftw!)
- Separate Daycare holding larger amount of Pokemon at once

I've tested it thoroughly and there doesn't seem to be any problems. I will be adding more and more features into this because I believe that it has the potential to become a very useful feature.
Currently planning to add:
- Party swap completely all in one go (this will actually be in the very near future..maybe today even :P)
- Partial swapping (believe it or not, this is hard because there's no graphical support)
- Suggest me more :D

How to insert:

Compile into free space the following routine:
Spoiler:

Here's a compiled version:
Code:
11 B5 38 48 01 68 00 29 32 D0 37 48 01 38 01 78 06 29 65 D0 01 30 50 22 51 43 40 18 34 49 09 78 32 4A 64 23 59 43 89 18 50 22 32 4B 00 F0 59 F8 2F 49 09 78 05 29 0B D0 05 22 52 1A 64 23 5A 43 2A 48 59 43 40 18 1B 18 19 1C 2A 4B 00 F0 49 F8 29 48 00 21 64 22 29 4B 00 F0 43 F8 22 48 01 38 02 78 27 49 0B 78 01 32 02 70 01 3B 0B 70 37 E0 23 48 00 78 06 28 33 D0 1C 49 64 22 50 43 40 18 04 1C 19 4B 1A 49 09 78 50 22 51 43 C9 18 19 4B 00 F0 27 F8 20 1C 1B 4B 00 F0 23 F8 14 48 00 78 05 28 0B D0 05 22 12 1A 50 23 5A 43 0E 49 58 43 40 18 1B 18 19 1C 0F 4B 00 F0 13 F8 0A 48 C8 21 49 00 40 18 00 21 50 22 0C 4B 00 F0 0A F8 06 48 01 38 02 78 0A 49 0B 78 01 3A 02 70 01 33 0B 70 1F BD 18 47 B8 70 03 02 01 C0 03 02 84 42 02 02 C0 70 03 02 09 0B 04 08 78 44 02 02 D9 5E 1E 08 29 40 02 02 7D E4 03 08
Usage:

The routine itself manages party storage and storage extraction. What you need to do is determine which one it performs.
If you want to remove a Pokemon from the party and into storage, setvar 0x8000 anything but zero
if you want to remove a Pokemon from storage, setvar 0x8000 0x0
Which variable you used can be changed, as always, by editing the pointer at the bottom of the routine.
The next thing is variable 0x8004. I use this variable to determine the slot of extraction for both the Party and the Storage system.
If I wanted to take the 3rd Pokemon in the party and put it in storage:
setvar 0x8004 0x2
setvar 0x8000 0x1
callasm 0x[routine] +1

The reason for this is to support easy use of special 0x9F. Though you can use copyvar, I suppose.

Finally, the routine writes to RAM a counter, which keeps track of how many Pokemon are in the storage.
This is written at 0x203C000, and can be retrieved by using the "copybyte" scripting command. For example:
copybyte 0x20370D0 0x203C000 'puts the storage counter into variable 0x800D (lastresult).

I tried to keep it simple, and do the work inside the routine, hopefully that paid off.
Here's a very poor sample script. Poor because it handles all the cases, but it doesn't display the system's full potential :P

Spoiler:

That's it for now. Keep an eye out for "addons" for this routine in the future :)
Sorry for the double post. I like seperate posts for my routines to keep the first post's links neat :x


So for anyone who has used this they know that only the Pre-Compiled version works, and the routine given does not compile to match either and don't work at all for that matter.

Also the Pre-Compiled version does work but has a bug from using Special 0x9F(Choose Pokemon from party).
If the player says yes to storing a Pokemon then decides to either press "B" or "Cancel" then the game will jump to the overworld view, glitch out and freeze with a Black screen.

Now I worked on this all day and was able to rebuild the Pre-Compiled routine so we could actually have the working source.
FBI's - Pre-Compiled Storage System - Disassembled/Rebuilt Routine
Code:
Code:
.text
.align 2
.thumb
.thumb_func

main:
push {r0, r4, lr}
    ldr r0, .FROM
    ldr r1,[r0]
    cmp r1, #0x0               @party
    beq addParty

addStorage:    
    ldr r0, .STORAGE
    sub r0, #0x1
    ldrb r1, [r0]
    cmp r1, #0x6               @limit of storage. Change depending on your space situation
    beq end
    add r0, #0x1
    mov r2, #0x50
    mul r1, r2
    add r0, r0, r1             @destination
    ldr r1, =(0x20370C0)       @ 2b Var_8004
    ldrb r1, [r1]
    ldr r2, .PARTY
    mov r3, #0x64
    mul r1, r3
    add r1, r1, r2             @source
    mov r2, #0x50              @size
    ldr r3, =(0x8040B09)       @memcpy_pkm 'void __fastcall memcpy_pkm(void *dst, void *src, unsigned int size)'
    bl linker
    ldr r1, =(0x20370C0)       @need to fix up Player's party slots @ 2b Var_8004
    ldrb r1, [r1]
    cmp r1, #0x5
    beq writeLastZero
    mov r2, #0x5
    sub r2, r2, r1
    mov r3, #0x64
    mul r2, r3                 @size
    ldr r0, .PARTY
    mul r1, r3
    add r0, r0, r1             @dest
    add r3, r3, r0
    mov r1, r3                 @src
    ldr r3, =(0x8040B09)       @memcpy_pkm 'void __fastcall memcpy_pkm(void *dst, void *src, unsigned int size)'
    bl linker
    
writeLastZero:
    ldr r0, =(0x2024478)       @ 100b    Party Pokemon 6
    mov r1, #0x0
    mov r2, #0x64
    ldr r3, =(0x81E5ED9)       @memset  'void __fastcall memset(char *dst, char pattern, int size)'
    bl linker

correctCounters:
    ldr r0, .STORAGE
    sub r0, #0x1
    ldrb r2, [r0]              @pks in storage counter
    ldr r1, =(0x2024029)       @ 1b    Repeattrainerbattle: Unknown. Loaded if battle type is 9.
    ldrb r3, [r1]              @pks in party
    add r2, #0x1
    strb r2,[r0]
    sub r3, #0x1
    strb r3, [r1]
    b end
    
addParty:
    ldr r0, =(0x2024029)       @ 1b    Repeattrainerbattle: Unknown. Loaded if battle type is 9.
    ldrb r0, [r0]
    cmp r0, #0x6
    beq end
    ldr r1, .PARTY
    mov r2, #0x64
    mul r0, r2
    add r0, r0, r1             @destination
    mov r4, r0
    ldr r3, .STORAGE
    ldr r1, =(0x20370C0)       @'var 0x8004 determines which slot of storage to take from'
    ldrb r1, [r1]
    mov r2, #0x50              @size
    mul r1, r2
    add r1, r1, r3             @source
    ldr r3, =(0x8040B09)       @memcpy_pkm 'void __fastcall memcpy_pkm(void *dst, void *src, unsigned int size)'
    bl linker
    mov r0, r4                 @update stats
    ldr r3, =(0x803E47D)       @pokemon_calc_effective_stats
    bl linker
    ldr r0, =(0x20370C0)       @adjust the storage   @ 2b Var_8004
    ldrb r0, [r0]
    cmp r0, #0x5               @storage limit minus 1
    beq writeZero
    mov r2, #0x5
    sub r2, r2, r0
    mov r3, #0x50
    mul r2, r3                 @size
    ldr r1, .STORAGE
    mul r0, r3
    add r0, r0, r1             @dest
    add r3, r3, r0
    mov r1, r3                 @src
    ldr r3, =(0x8040B09)       @memcpy_pkm 'void __fastcall memcpy_pkm(void *dst, void *src, unsigned int size)'
    bl linker

writeZero:
    ldr r0, .STORAGE
    mov r1, #0xC8
    lsl r1, r1, #0x1
    add r0, r0, r1
    mov r1, #0x0
    mov r2, #0x50 
    ldr r3, =(0x81E5ED9)       @memset  'void __fastcall memset(char *dst, char pattern, int size)'
    bl linker
    
updateCounters:
    ldr r0, .STORAGE
    sub r0, #0x1
    ldrb r2, [r0]
    ldr r1, =(0x2024029)       @ 1b    Repeattrainerbattle: Unknown. Loaded if battle type is 9.
    ldrb r3, [r1]
    sub r2, #0x1
    strb r2,[r0]
    add r3, #0x1
    strb r3, [r1]

end:
    pop {r0-r4, pc}
    
linker:
    bx r3

.align 2

.FROM:
    .word 0x20370B8            @var_8000

.STORAGE:
    .word 0x203C001            @storage location

.PARTY:
    .word 0x2024284            @player's party
And to go along with that is the XSE script.
Code:
Code:
#dynamic [COLOR=DarkOrange]0xFreeSpaceToStartFrom[/COLOR]

//---------------
#org @start
lock
faceplayer
copybyte 0x20370D0 0x203C000
compare 0x800D 0x0
if 0x1 goto @snippet1
msgbox @string1 0x5 //"Want your Pokemon back?"
compare 0x800D 0x1
if 0x1 goto @snippet2
goto @snippet1

//---------------
#org @snippet1
countpokemon
copyvar 0x8000 0x800D
compare 0x8000 0x1
if 0x3 goto @snippet3
msgbox @string2 0x5 //"Want to give me a pokemon?"
compare 0x800D 0x1
if 0x1 goto @snippet4
msgbox @string3 0x6 //"Alright, next time then."
release
end

//---------------
#org @snippet2
setvar 0x8000 0x0
countpokemon
compare 0x800D 0x6
if 0x1 goto @snippet5
msgbox @string4 0x6 //"Alright, I'll give it to you."
setvar 0x8004 0x0
[COLOR=DarkOrange]callasm 0xWhereYouPutYourTheRoutine+1[/COLOR]
fanfare 0x101
msgbox @string5 0x6 //"I gave it back."
release
end

//---------------
#org @snippet3
msgbox @string6 0x6 //"Hi, I can't do anything\nyour slot..."
release
end

//---------------
#org @snippet4
setvar 0x8000 0x1
special 0x9F
waitstate
lockall
compare 0x8004 0x7
if 0x1 goto @snippet6
countpokemon
compare 0x800D 0x1
if 0x3 goto @snippet6
[COLOR=DarkOrange]callasm 0xWhereYouPutYourTheRoutine+1[/COLOR]
msgbox @string7 0x6 //"Thanks for giving me this."
release
end

//---------------
#org @snippet5
msgbox @string8 0x6 //"You're party is full!"
release
end

//---------------
#org @snippet6
msgbox @string3 0x6 //"Alright, next time then."
release
end


//---------
// Strings
//---------
#org @string1
= Want your Pokemon back?

#org @string2
= Want to give me a pokemon?

#org @string3
= Alright, next time then.

#org @string4
= Alright, I'll give it to you.

#org @string5
= I gave it back.

#org @string6
= Hi, I can't do anything\nyour slots are full or empty\lor mine are full while yours are\lfull[.]

#org @string7
= Thanks for giving me this.

#org @string8
= You're party is full!
Edit the orange text before compiling.


Hope this helps anyone.
When I get the time I will see what I can do about fixing the bug as well.


Edit_Two:
Found the bug!
Special 0x9F lets you choose any Pokemon as well as Eggs.
And,
Special 0xBC lets you choose any Pokemon beside Eggs(used for daycare)
When pressing B var 0x8004 is set to 0x07 so I simply added a compare to fix the script.
 
Last edited:
352
Posts
7
Years
  • Age 30
  • Seen Mar 10, 2022
I think he wants to set a default name while skipping the intro. If you skip the intro via ASM, the default name is left as 0s aka blank.

Setting a static name to the player


Well, this is beyond simple, lol. I'll keep my post the same format though, because first post :3

How to insert:

Before you begin to insert the routine, there are a few steps. Firstly player names are limited to 8 characters with the eighth character = 0xFF.
Convert the static name you want from ascii to hex. For OP, he wanted Jesse and James which convert into:
C4 D9 E7 E7 D9 FF FF FF - Jesse
C4 D5 E1 D9 E7 FF FF FF -James
Note that if all eight bytes don't get used, you should pad them with "FF" in your hex editor.
Now insert the 8 byte names into some free space in your ROM via hex editor and write down the pointers.

Now copy the following routine into a text editor:
Spoiler:


You'll notice that I have the lines:
Code:
.CustomNameBoy:
	.word 0x@pointer to boy name

.CustomNameGirl:
	.word 0x@pointer to girl name

Change the 0x@pointer text to 0x[offset you inserted]. No need to add one.
After you've done that compile and insert into free space.

Usage:
You must callasm to the routine, and depending on the Player's gender it will set their name. To have their name inserted before the player starts playing the game, create a level script which calls this routine. If you don't know how, ask in a relevant thread (not here).

It works, but the female player name becomes the same as the male.
 
Last edited:

Wesley FG

Pokémon Kalos Advance !! Gba Hack
338
Posts
15
Years
I've noticed significant demand for working Dawn Stone evolutions, specifically ones that require the mon to be a specific gender. My bad if this is already posted somewhere but here y'all go:

Code:
.org 0x4318e
lsl r0, r0, #0x0
ldr r2, .MethodAddr
bx r2

.MethodAddr: .word 0x085B2521 #UPDATE THIS TO MAIN FUNCTION OFFSET+1


.org 0x5B2520 #UPDATE THIS TO MOST CONVENIENT FREE SPACE IN YOUR HACK
cmp r0, #0x7
beq StandardStone
cmp r0, #0x14 #UPDATE THIS
beq MaleStone
cmp r0, #0x15 #UPDATE THIS
beq FemaleStone
b NoEvo

MaleStone:
push {r1-r3}
mov r0, r7
mov r1, r8
ldr r1, [r1, #0x0]
bl DetermineGender
pop {r1-r3}
cmp r0, #0x0
beq StandardStone
b NoEvo


FemaleStone:
push {r1-r3}
mov r0, r7
mov r1, r8
ldr r1, [r1, #0x0]
bl DetermineGender
pop {r1-r3}
cmp r0, #0xFE
beq StandardStone
b NoEvo


StandardStone:
ldrh r0, [r1, #0x2]
cmp r0, r9
beq Finish

NoEvo:
ldr r2, .NoEvoReturn
bx r2

DetermineGender:
ldr r2, .DetermineGenderFunc
bx r2

Finish:
ldr r2, .EvoReturn
bx r2

.NoEvoReturn: .word 0x08043199
.EvoReturn: .word 0x0804317d
.DetermineGenderFunc: .word 0x0803f78d
Change the values in the lines marked UPDATE THIS to the indexes of male stone evos and female stone evos. Leave their entries blank in the general evolution table; stone evolutions function differently from level-up evolutions.

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
 
352
Posts
7
Years
  • Age 30
  • Seen Mar 10, 2022
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...)
 
232
Posts
12
Years
  • Seen Sep 10, 2019
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:
 
5,256
Posts
16
Years

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

Wesley FG

Pokémon Kalos Advance !! Gba Hack
338
Posts
15
Years
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
q_zpshnquzant.gif
 
232
Posts
12
Years
  • Seen Sep 10, 2019
REQUEST for FR:

A 'givepokemon' routine that allows the user to set custom OT name and TID/SID. (useful for creating legal event pokemon)
 
232
Posts
12
Years
  • Seen Sep 10, 2019
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:



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
 
Last edited by a moderator:

Blah

Free supporter
1,924
Posts
11
Years
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:


Untested, and may not compile as is. Post updates here please.
 
232
Posts
12
Years
  • Seen Sep 10, 2019
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:


Untested, and may not compile as is. Post updates here please.
Works well, thank you!
 
352
Posts
7
Years
  • Age 30
  • Seen Mar 10, 2022

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:


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?
 
Back
Top