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)

Lunos October 28th, 2018 6:52 PM

Quote:

Originally Posted by pokemontutorialTV (Post 9938338)
If I use the above routine, the price isnt calculated for non-TM shops correctly anymore. Do I something wrong?
Ok, I know know your routine does some mistakes with the registers. If you want a working soulution, also shorter than this, DM me.

Consider just sharing it here directly for everyone's benefit. Thank you.

ghoulslash November 6th, 2018 2:42 PM

[FR] Fully Flag-Dependent Start Menu

It's nothing fancy, but this code expands on FBI's routine to swap between start menus, shown here. It also keeps the safari zone start menu intact.

Every single start menu option (except Exit) is flag-dependent, so you can add or remove start menu options with simple flag setting/clearing.

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global start_menu
/*
insert 00 48 00 47 (xx+1) xx xx 08 at 6ed5c

*/

.equ offset, 0x08xxxxxx                @ insert location

/* change these */
.equ DEX_FLAG, 0x250
.equ POKE_FLAG, 0x251
.equ BAG_FLAG, 0x252
.equ PLAYER_FLAG, 0x253
.equ SAVE_FLAG, 0x254
.equ OPT_FLAG, 0x255
.equ EXIT_FLAG, 0x0  @ currently unused, so at least 1 option is shown

Main:
        bl check_safari_zone
        cmp r0, #0x1
        bne regular_menu
        ldr r0, =(0x0806ed86 +1)
        bx r0

regular_menu:
        push {r4-r5}
        mov r1, #0x0
        ldr r4, =(offset+table)

loop:
        lsl r0, r1, #0x2
        add r0, r0, r4
        mov r5, r0
        cmp r1, #0x6
        beq add_option        @ auto-add last option (exit)
        ldrh r0, [r5]        @ flag to check
        push {r1}
        bl check_flag
        pop {r1}
        cmp r0, #0x1
        bne loop_incr

add_option:
        ldrb r0, [r5, #0x2]                @ menu index
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        push {r1}
        bl add_opt
        pop {r1}

loop_incr:
        cmp r1, #0x6        @ num opts
        beq exit
        add r1, #0x1
        b loop

exit:
        pop {r4-r5}
        pop {r0}
        bx r0

.align 2
table:
.hword DEX_FLAG
.byte 0
.byte 0
.hword POKE_FLAG
.byte 1
.byte 0
.hword BAG_FLAG
.byte 2
.byte 0
.hword PLAYER_FLAG
.byte 3
.byte 0
.hword SAVE_FLAG
.byte 4
.byte 0
.hword OPT_FLAG
.byte 5
.byte 0
.hword EXIT_FLAG
.byte 6
.byte 0

check_flag:
        ldr r2, =(0x0806e6d0 +1)
        bx r2

add_opt:
        ldr r2, =(0x0806ed94 +1)
        bx r2

check_safari_zone:
        ldr r0, =(0x080a0e90 +1)
        bx r0




for example, with the current definitions, setting flags 0x251, 0x253 would make the start menu be composed of only "Pokemon","[player]", and "Exit".

Skeli November 9th, 2018 1:00 PM

Quote:

Originally Posted by Petuuuhhh (Post 9946301)
Potions go into the Key Item slot when I use this? What am I doing wrong?

You need to delete your save file and start a new game. Or, implement this routine by Sagiri, and then you can just start a new game normally. If you used the saveblock routine from this post and you do implement Sagiri's routine, make sure that you change the first line in constants.s (from Sagiri's routine) to
Code:

.definelabel jpan_block, 0x0203C100


as that is where I started the saveblock in JPAN's routine.

Zeturic November 9th, 2018 5:07 PM

Since it got mentioned above, I figured I'd post this here.

It's been tweaked slightly so that it only uses armips, rather than the build system I use for my C stuff. All it really did for it was find free space automatically, and, while that's kind of useful, I feel it unnecessarily overcomplicated it.

In any case:

Clear JPAN Save Block During New Game [FR]

Fixes an oddity with JPAN's Save Block Recycle where the saved memory doesn't get zeroed upon starting a new game. Instead, it'll retain whatever it happened to be in the previous save file.

To be clear, this does not actually include JPAN's Save Block Recycle itself.

Zeturic November 10th, 2018 9:35 PM

Unhidden Power [FR]

This routine makes the game calculate and display the actual type of Hidden Power in battle and in status screens. If, for example, a Pokémon's Hidden Power type is Water, it will display as a Water-type move, just like Surf or any other Water-type move.

https://github.com/Sagiri/unhidden-power/blob/master/in-battle.png?raw=true https://github.com/Sagiri/unhidden-power/blob/master/status-screen.png?raw=true

Note that this only calculates and displays the type, not the base power.

Zeturic November 12th, 2018 5:15 PM

Evolve by Leveling Up While Holding An Item [FR]

Adds evolution methods to allow Pokémon to evolve by leveling up while holding a particular item. Also included are day and night variations for use with Happiny, Gligar, and Sneasel.

Other implementations of this evolution method have a subtle bug - they remove the item even if the player hits B to cancel the evolution. This avoids that.

Zeturic November 15th, 2018 1:14 AM

Summary Screen Wraps Around [FR]

Allows you to hit Up on the summary screen of the first Pokémon in the party to move to the last Pokémon in your party, and likewise hit Down on the last to move to the first. This change originated in XY and has become standard in all later games.

eMMe97 November 15th, 2018 8:39 AM

Are there news about this feature? (Trainer's Interrupting battles)
I see that Chacha Dinosaur imported it in Emerald, but for Fire Red?

Megax Rocker November 16th, 2018 6:45 AM

Did someone ever make a Pixie plate item effect?

Zeturic November 17th, 2018 4:27 PM

Hall of Fame Expanded Pokémon Fix [FR]

Fixes an issue where expanded Pokémon above index 0x1FF do not show up correctly in the Hall of Fame.

For example, 0x201 would normally show up as 0x1 (Bulbasaur). This is because the Hall of Fame data only allocated 9 bits to the species number, and 0x1FF is the largest number that can be stored in that space; larger numbers only have their lowest 9 bits stored.

pikachux2 November 19th, 2018 1:55 PM

I literally no nothing about Assembly in fire red, but is the limited number of flags in fire red really a problem? Is it not possible to make an ASM routine that can check the value of some offset after 800000 and return a pseudo Boolean value to the last result variable 0x800D (or any other for that matter)? This will probably be an easy yes or no for a lot of you, I was just curious.

hacanoc November 28th, 2018 3:48 PM

Quote:

Originally Posted by FBI (Post 8620314)

Changing the Player's Overworld ingame



Intro:

I recently made this routine, it's kind of limited in the sense that you can only be change to 30 different overworlds (excluding the special version of the default characters). While it is limited, I don't really think that that's a problem (you'd probably only be OWs swapping to 2-3 different OWs the entire game anyways, so unless you wanted to player to play as more than 30 characters, this routine will work just fine for you). It's also a little "smaller" in comparison to JPAN's 6 seperate routines which he used (though in his favor, I don't think his limits the amount like mine). I blame the table, it's weird. Actually the whole overworld loading thing is weird..it's done in like 9 places lol.

I should also note that if the OW you're changing to doesn't have a running frame, things are going to look weird when you try to run~

How to insert:

Compile into free space the following routine:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

@hook from 0805CA4C via r0

main:
        @flag check
checkFlag:
        mov r0, #0xFF
        lsl r0, r0, #0x2
        add r0, r0, #0xA @0x3FC + 0xA = @406
        ldr r2, =(0x806E6D0 +1)
        push {r1, r3}
        bl linker
        pop {r1, r3}
        cmp r0, #0x1
        bne noCrash

setOW:
        ldr r0, =(0x20370B8)
        ldrb r0, [r0]
        cmp r0, #0xFF
        beq noCrash
        mov r3, r0

noCrash:
        mov r8, r3
        lsl r4, r4, #0x10
        lsr r4, r4, #0x10
        lsl r5, r5, #0x10
        ldr r0, =(0x805CA54 +1)
        bx r0

linker:
        bx r2

.align 2


Here's a compiled version:
Code:

FF 20 80 00 0A 30 09 4A 0A B4 00 F0 0E F8 0A BC 01 28 04 D1 06 48 00 78 FF 28 00 D0 03 1C 98 46 24 04 24 0C 2D 04 03 48 00 47 10 47 D1 E6 06 08 B8 70 03 02 55 CA 05 08




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

00 48 00 47 XX XX XX 08


Where XX XX XX is where you inserted this routine +1.


Usage:

The routine requires two conditions to toggle.
1) Flag 0x406 is set
2) Var 0x8000 is not 0xFF

As you may have guessed you need to set variable 0x8000 to a value which matches the overworld you want the player to transform into. Please note that for the effect to happen, you need to warp first.
Here's a list of values and their corresponding sprite to the left:
Spoiler:

Code:

0 - male hero
1 - female hero
3 - female hero bike
4 - male hero run
5 - female hero run
6 - male hero vs-seeker
7 - female hero vs-seeker
8 - male hero fishing
9 - female hero fishing
12 - Brendon
13 - May
26 - Male + Female hero Vs seeker on bike
28 - Random guy (A-MAP ID 25)
29 - Little boy
44 - Gem sign thing (buggy)
48 - Spearow
52 - Old man 1 (A-MAP ID 33)
80 - Jogging girl
83 - Blonde dude (A-MAP ID 26)
84 - Fat guy
88 - Old man 2 (A-MAP ID 88)
92 - Scroll backpack thing (buggy)
93 - Team rocket male
104 - Meowth
112 - Chansey
116 - Slowbro
124 - Snorlax
125 - Fisherman
166 - Kid tuber (male)
170 - Old man 3 (A-MAP ID 30)
176 - Green girl (A-MAP ID 40)
213 - Red dress lady
214 - Old lady
228 - Deoxys (I think this one is normal)
245 - Misty
250 - Hey champ in the making guy
251 - Ghost Girl



While no particular value will cause a crash, I've excluded values which are "repeated" OWs. If you experience bugs, use it in conjunction with the backsprite hack I made. If you still have bugs, report them here!

Hi
I tried to apply this rutine but i got errors:
The change of the OW is lost after the player enter in a menu or enter in a battle.
I also inserted the rutine of swap BS, in that i get a problem with the change of the OW after a warp (the OW change to the Hero surfing or the hero in bike)

https://i.postimg.cc/1XDTPSvf/Error-OWGIF.gif

What can I do?

opakedragon December 23rd, 2018 10:16 PM

Quote:

Originally Posted by Lunos (Post 9800566)
Welp, it didn't work.
I compiled the routine and dropped it in the offset 71A250, wrote this script and once I checked it In-Game, this was the result.
https://i.imgur.com/yGrrQAK.png
Note: Just for the record, the savefile is right after defeating my Rival for the very first time, so there's no way for my Pokémon to have 76 points.

Dunno if you'll be able to fix it, but in any case thank you very much.

Would you be willing to reshare the script (the link is no longer working) in code tags? I am relatively new and trying to figure this stuff out.

ShinypikachuX January 7th, 2019 6:02 AM

how about in game rival naming

eMMe97 January 13th, 2019 3:09 AM

Does anyone know if this function (Steven battle for fire red) has been completed? They wrote that it would be enough to insert a line of code to make it complete, but unfortunately it seems that no one has chosen how to insert it.

Delta231 January 13th, 2019 5:00 AM

Quote:

Originally Posted by eMMe97 (Post 9967356)
Does anyone know if this function (Steven battle for fire red) has been completed? They wrote that it would be enough to insert a line of code to make it complete, but unfortunately it seems that no one has chosen how to insert it.

No this wasn't completed and I prefer to use Decompilations.

Blah January 17th, 2019 2:37 PM

Quote:

Originally Posted by eMMe97 (Post 9967356)
Does anyone know if this function (Steven battle for fire red) has been completed? They wrote that it would be enough to insert a line of code to make it complete, but unfortunately it seems that no one has chosen how to insert it.

This is done for the typical encounter battles (where you meet eyes with two trainers at once). What isn't done is a scripted double battle. That shouldn't be hard given the source code here. The caution is that it isn't thoroughly bug tested because CommHack never took off past the mapping (rip scripters).

eMMe97 January 18th, 2019 12:37 AM

Quote:

Originally Posted by FBI (Post 9968968)
This is done for the typical encounter battles (where you meet eyes with two trainers at once). What isn't done is a scripted double battle. That shouldn't be hard given the source code here. The caution is that it isn't thoroughly bug tested because CommHack never took off past the mapping (rip scripters).

I had misunderstood how it worked then, thanks for the clarification!
If I can help, I'll get along well with the fire red scripting :)

Lunos January 26th, 2019 4:23 PM

Quote:

Originally Posted by Spherical Ice (Post 9633537)

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


I've used this many many times, I love this feature as silly it may sound.
Surprisingly though, I noticed just now that it seems to glitch the blue bar containing the different HMs descriptions inside the Pokémon Party menu. Could anyone confirm?
https://i.imgur.com/pdFcrC7.png

Steps that I did:
1) Inserted the text string in 0x456734
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


2) Copy and pasted the routine in a text file, then I modified the offset in L39 accordingly (0x08456734) and compiled.
The result was:
Code:

30 B5 00 06 04 0E A0 00 00 19 C0 00 15 49 45 18 15 48 C1 8D 03 20 08 40 00 28 1F D0 05 20 13 4B 00 F0 1F F8 0A 21 68 5A 04 28 13 D1 02 21 68 5A 09 28 0F DD 0C 20 01 21 0D 4B 00 F0 12 F8 00 06 00 0E 01 28 06 D1 0B 49 0B 4A 20 1C 0B 4B 00 F0 08 F8 03 E0 20 1C 08 4B 00 F0 03 F8 30 BC 01 BC 00 47 18 47 98 50 00 03 F0 30 00 03 CD 22 07 08 85 A0 09 08 34 67 45 08 99 BF 09 08 5D F7 13 08


3) Inserted the routine in 0x45675C

4) Went to 0x9BF64 and wrote: 5D 67 45 08

5) Saved and tested.

I'm certainly getting the extra Premier Ball if I purchase 10 Poké Balls. No issues there.
The thing is that if I grab a clean ROM and this is the only thing that I add to it, the issue with the blue bar happens :/

Subzero Eclipse January 27th, 2019 3:45 AM

Quote:

Originally Posted by Lunos (Post 9972584)
I've used this many many times, I love this feature as silly it may sound.
Surprisingly though, I noticed just now that it seems to glitch the blue bar containing the different HMs descriptions inside the Pokémon Party menu. Could anyone confirm?
https://i.imgur.com/pdFcrC7.png

Steps that I did:
1) Inserted the text string in 0x456734
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


2) Copy and pasted the routine in a text file, then I modified the offset in L39 accordingly (0x08456734) and compiled.
The result was:
Code:

30 B5 00 06 04 0E A0 00 00 19 C0 00 15 49 45 18 15 48 C1 8D 03 20 08 40 00 28 1F D0 05 20 13 4B 00 F0 1F F8 0A 21 68 5A 04 28 13 D1 02 21 68 5A 09 28 0F DD 0C 20 01 21 0D 4B 00 F0 12 F8 00 06 00 0E 01 28 06 D1 0B 49 0B 4A 20 1C 0B 4B 00 F0 08 F8 03 E0 20 1C 08 4B 00 F0 03 F8 30 BC 01 BC 00 47 18 47 98 50 00 03 F0 30 00 03 CD 22 07 08 85 A0 09 08 34 67 45 08 99 BF 09 08 5D F7 13 08


3) Inserted the routine in 0x45675C

4) Went to 0x9BF64 and wrote: 5D 67 45 08

5) Saved and tested.

I'm certainly getting the extra Premier Ball if I purchase 10 Poké Balls. No issues there.
The thing is that if I grab a clean ROM and this is the only thing that I add to it, the issue with the blue bar happens :/

Hey man, I have inserted this routine in my ROM hack as well and everything is fine on my end. I would guess that this thing happens because you have put the routine before 71A240: in the past I have tried to insert other routines in free space before it and I have had the same issue as you, but when I do put them over 71A240, no problem at all. Maybe you should try to insert it somewhere there and see what happens? Hope it helps.

Lunos January 27th, 2019 6:29 AM

Quote:

Originally Posted by Funny Valentine (Post 9972783)
Hey man, I have inserted this routine in my ROM hack as well and everything is fine on my end. I would guess that this thing happens because you have put the routine before 71A240: in the past I have tried to insert other routines in free space before it and I have had the same issue as you, but when I do put them over 71A240, no problem at all. Maybe you should try to insert it somewhere there and see what happens? Hope it helps.

I just tried it out, and now it's certainly working perfectly. That's kinda dissapointing though, but eh, I guess the free space before 71A240 could be used for something else like maps or scripts..?
Anyway, thank you :D!

EDIT:
Quote:

Originally Posted by FBI (Post 8514906)

Inheriting IVs from parents (via Destiny Knot, in the daycare)


I was testing this routine out just now, and I'm not entirely sure if it's working correctly.
It looks to me like the Eggs are inheriting 3 stats alone, when they should always inherit 5 stats :/
I've been doing tests using this routine and Jiangzhengwenjz's EV-IV Screen.

In my last attempt for example, the results of the Egg were:
-03 HP IVs. Charmander has 30 and Ditto 26.
-03 Atk IVs inherited from Charmander.
-22 Def IVs inherited from Charmander or Ditto (both have 22 Def IVs.)
-23 Spd IVs. Charmander has 31 and Ditto 25.
-19 SpAtk IVs. Charmander has 31 and Ditto 10.
-31 SpDef IVs inherited from Ditto.

If we assume that HP is the random stat in this spread, Spd and SpAtk are the issue here.
The Egg should have inherited Charmander's or Ditto's values in those stats after all, right?
Has anyone tested this yet?

ghoulslash February 5th, 2019 4:33 PM

[FR] Selection from PC Box

This hack allows the player to directly select a pokemon from the pc boxes by modifying the tasks associated with the withdraw function. It doesn't actually do anything with the selection except store relevant data, but this data can then be used in subsequent functions to modify relevant data.

Fortunately, I added in some new/updated specials to allow the user to swap pokemon between box and party for things like trading, nicknaming, and checking/setting pokeball types. Adding new specials for other data manipulation is easy enough, and I would be happy to add more if more ideas come to me.

Current Special Fixes Include:
Spoiler:

special 0x7 - get EVs of party/boxed pokemon
special 0x8 - get IVs of party/boxed pokemon
special 0xB - get pokeball ID of party/boxed pokemon
special 0xD - get happiness of party/boxed pokemon
special 0x13 - set happiness of party/boxed pokemon
special 0x14 - ste pokeball ID of party/boxed pokemon
special 0x1A - save/restore party pokemon data to/from free ram (default is 6th opponent slot)
special 0x1B - save/restore pokemon data to/from pc
special 0x7b - check nicknamed pokemon from party/box
special 0x7c - buffer party/boxed pokemon nickname
special 0x7d - check traded pokemon from party/box
special 0x9e - nickname pokemon from party/box


Here is the repository. The readme should do an adequate job of detailing the usage.

Here is a GIF of using this function with a wonder trade. (credit to sagiri for the dtan system)
https://i.imgur.com/zq6pr9c.gif

Delta231 February 5th, 2019 7:02 PM

Quote:

Originally Posted by ghoulslash (Post 9976338)
[FR] Selection from PC Box

This hack allows the player to directly select a pokemon from the pc boxes by modifying the tasks associated with the withdraw function. It doesn't actually do anything with the selection except store relevant data, but this data can then be used in subsequent functions to modify relevant data.

Fortunately, I added in some new/updated specials to allow the user to swap pokemon between box and party for things like trading, nicknaming, and checking/setting pokeball types. Adding new specials for other data manipulation is easy enough, and I would be happy to add more if more ideas come to me.

Here is the repository. The readme should do an adequate job of detailing the usage.

Here is a GIF of using this function with a wonder trade. (credit to sagiri for the dtan system)
https://i.imgur.com/zq6pr9c.gif

May I request to remove those .exe files in the repository as not everyone in this community uses Windows and you can just link to those utilities .

Bidoof February 9th, 2019 10:31 PM

Hello, I am interested in hacking the wild pokemon generator of Fire Red to influence the species in a similar manner as Static and Magnet Pull do in later games. I've searched many places, including this thread, but I have not found a routine for this. Does anyone know if this has been done before? If not, could you kindly give me advice on how to approach this problem? I am new to ASM but I have experience from other languages so I'm not a total beginner. I know how to compile and insert routines.

AkameTheBulbasaur February 12th, 2019 6:35 PM

It doesn't break flashcart compatibility if you're using the newest version, but it does mean you can't use Save Editors anymore, and you have to start a new save file. This may not be ideal for everyone (it wasn't for me), so here is the way to free up some RAM that gets saved.

To free up the RAM just do the following:

1. Put 28 E0 at 0x110F24
2. Put 04 20 at 0x11192A
3. Put 70 47 at 0x110AEC
4. Put 70 47 at 0x1123BC

This will free up about 8000 flags and 2900 vars (numbers are approximate). Full details are in this post below (ORIGINALLY BY JPAN SO THANK HIM)

https://www.pokecommunity.com/showpost.php?p=8795370&postcount=4

The RAM that I used to free up item space started at 0x2026840 and believe me it is plenty of space. What will happen is that you will lose any items currently in your bag after you switch over. So you'll need to deposit them/give them to PC Pokemon if you want to keep them (alternatively you can write a routine to move the data at the original item RAM over to the new one).

If you have a previous save file, your bag will be a bunch of junk because the save file wrote stuff in the RAM from the Previously On Your Quest thing. To fix that use this routine:

Spoiler:

.text
.align 2
.thumb
.thumb_func

Main:
push {r4-r5, lr}

ClearItems:
ldr r4, .RAMStart
mov r0, #0x0
Loop:
str r0, [r4]
add r4, r4, #0x4
ldr r5, .RAMEnd
cmp r4, r5
beq Return
b Loop

Return:
pop {r4-r5, pc}

.align 2
.RAMStart: .word 0xPLACE WHERE RAM STARTS
.RAMEnd: .word 0xPLACE WHERE RAM ENDS


This routine just makes everything in the RAM range go to zero (so your bag will then be empty and you can put all your items back in).

To use the above routine just insert it and then write an NPC using callasm and call the routine. Then just talk to the NPC you gave it to in-game, save and you'll be done. You can delete the routine and the script afterwards if you want to.

Skeli February 13th, 2019 9:09 PM

Quote:

Originally Posted by Skeli- (Post 9743323)
Expanding the Bag Entirely [FR]
]

This has been updated with fixes for the Old Man battle, Teachy TV, and expanded berries.

Golddron February 17th, 2019 4:38 AM

I've been working on a FR hack for a few months recreating Pokémon Colosseum/Gale of Darkness. About 95% done with the trainer editing (The shadow pokemon concept wasn't really working out as I was having trouble catching a specific pokemon from a trainer's party, so I've just been using the givepokemon command after the battle and using the flags from various overworld item sprites).

I'd really like to add a function where an opponents party level matches the highest in your party, like in the Mt Battle area in those games. Is there a way to set that up in a specific area of the game? Like to pull a certain trainer hex ID into the trainerbattle command and temporarily adjust the levels from their original setting to the highest in your party? Or would entirely new trainers have to be made? I'm leaning toward that because I've tried to find the trainers in the Trainer Tower in FR but they don't seem to be available to edit in trainer editing programs.

I've been scouring threads looking for info on this, but haven't had much luck. If anyone is able to help, wants to take a crack at it, or point me in the right direction I'd greatly appreciate it.

EDIT

I've come across how to get the highest level in my party, but I'm unsure how to have the game temporarily overwrite the trainer's pokemon level with a script, so I was thinking an ASM routine might be the way to go.

eMMe97 February 17th, 2019 2:17 PM

Quote:

Originally Posted by ghoulslash (Post 9976338)
[FR] Selection from PC Box

This hack allows the player to directly select a pokemon from the pc boxes by modifying the tasks associated with the withdraw function. It doesn't actually do anything with the selection except store relevant data, but this data can then be used in subsequent functions to modify relevant data.

Fortunately, I added in some new/updated specials to allow the user to swap pokemon between box and party for things like trading, nicknaming, and checking/setting pokeball types. Adding new specials for other data manipulation is easy enough, and I would be happy to add more if more ideas come to me.

Current Special Fixes Include:
Spoiler:

special 0x7 - get EVs of party/boxed pokemon
special 0x8 - get IVs of party/boxed pokemon
special 0xB - get pokeball ID of party/boxed pokemon
special 0xD - get happiness of party/boxed pokemon
special 0x13 - set happiness of party/boxed pokemon
special 0x14 - ste pokeball ID of party/boxed pokemon
special 0x1A - save/restore party pokemon data to/from free ram (default is 6th opponent slot)
special 0x1B - save/restore pokemon data to/from pc
special 0x7b - check nicknamed pokemon from party/box
special 0x7c - buffer party/boxed pokemon nickname
special 0x7d - check traded pokemon from party/box
special 0x9e - nickname pokemon from party/box


Here is the repository. The readme should do an adequate job of detailing the usage.

Here is a GIF of using this function with a wonder trade. (credit to sagiri for the dtan system)
https://i.imgur.com/zq6pr9c.gif

GREAT!!!!
Can u make a example script please? I don't understand how to make it (I just read the README text in the repository). Thank you :)

rubenturen February 18th, 2019 1:59 AM

im using emerald
Hello I wanted to know if there
Is a way to make a asm routine that I can call in a script Wich shows a trainer battle sprite anywhere on screen
Like a modified showpokepic or something

(P.s. i’m Not good at making asm myself so pls design the routine for me)

ghoulslash February 18th, 2019 11:19 AM

Quote:

Originally Posted by eMMe97 (Post 9980856)
GREAT!!!!
Can u make a example script please? I don't understand how to make it (I just read the README text in the repository). Thank you :)

There is an example nicknaming script at the bottom of the readme file.

The usage is essentially:
Code:

writebytetooffset 0x1 <state tracker ram>
special 0x3c
waitstate
writebytetooffset 0x0 <state_tracker ram>


This will let you select a pokemon from the box, and store the relevant location information to var8000 and var8001. Then, using the updated specials you can manipulate that pokemon's data.

eMMe97 February 18th, 2019 2:35 PM

Ok. But how can insert 2 Pokémon in the box? For example bulbasaur e squirtle?

ghoulslash February 18th, 2019 8:29 PM

Quote:

Originally Posted by eMMe97 (Post 9981292)
Ok. But how can insert 2 Pokémon in the box? For example bulbasaur e squirtle?

The routine doesn't let you deposit pokemon to the box, just select them. The hack itself does nothing except save useful information.

uchiwaobito February 19th, 2019 9:20 AM

Quote:

Originally Posted by GoGoJJTech (Post 8881333)
For Emerald (Changes in Red):
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r7}
        ldr r0, =(0x20244EC) @Party Pokémon
        mov r6, #0x0
        ldr r7, =(0x20244E9) @Party Quantity
        ldrb r7, [r7]

loop:
        cmp r6, r7
        beq end
        mov r1, #0x64
        mul r1, r1, r6
        add r0, r0, r1
        mov r5, r0
        mov r1, #0x39
        ldr r3, =(0x806A518 +1) @Pokemon Get Attribute
        bl linker
        mov r4, r0
        cmp r4, #0x0
        beq next
        mov r0, r5
        mov r1, #0x3A
        ldr r3, =(0x806A518 +1) @Pokemon Get Attribute
        bl linker
        add r6, r6, #0x1
        cmp r4, r0
        beq loop

addOn:
        add r4, r4, #0x3 @amount to add per step. Here it's 3
        cmp r4, r0
        ble cont
        mov r4, r0

cont:
        mov r0, r5
        mov r1, #0x39
        ldr r2, =(0x20375F0) @Var 0x800D (Lastresult)
        strh r4, [r2]
        ldr r3, =(0x806ACAC) @Pokemon Set Attribute
        bl linker
        b loop

next:
        add r6, r6, #0x1
        b loop

end:
        pop {r0-r7}
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        cmp r0, #0x1
        beq brancher
        mov r0, r5
        ldr r1, =(0x809C8F4 +1)
        bx r1

brancher:
        ldr r0, =(0x809C92E +1) @This may actually fail the routine, needs testing
        bx r0

linker:
        bx r3

.align 2



Insert at 0x9C8EA.

Nice idea, however it didn't work for Pokemon Emerald BPEE, it automatically reset when the char moves.

Lunos March 4th, 2019 11:38 PM

Quote:

Originally Posted by opakedragon (Post 9960020)
Quote:

Originally Posted by Lunos (Post 9800566)
Quote:

Originally Posted by ghoulslash (Post 9800529)
Here you go! (admittedly I have not tested it)

Code:

.text
.align 2
.thumb
.thumb_func
.global GetHappiness

Main:
        push {r0-r2, lr}
        ldr r0, .var8004
        ldrb r0, [r0]        @slot num
        mov r1, #0x64
        mul r0, r1
        ldr r1, .PartyData
        add r0, r1, r0
        mov r1, #0x20        @happiness
        bl GetAttribute
        ldr r1, .var8004
        strb r0, [r1, #0x2]        @store into var8005
        pop {r0-r2, pc}

GetAttribute:
        ldr r2, =(0x0803FBE8 +1)
        bx r2

.align 2
.PartyData:        .word 0x02024284
.var8004:        .word 0x020370C0



Welp, it didn't work.
I compiled the routine and dropped it in the offset 71A250, wrote this script and once I checked it In-Game, this was the result.
https://i.imgur.com/yGrrQAK.png
Note: Just for the record, the savefile is right after defeating my Rival for the very first time, so there's no way for my Pokémon to have 76 points.

Dunno if you'll be able to fix it, but in any case thank you very much.

Would you be willing to reshare the script (the link is no longer working) in code tags? I am relatively new and trying to figure this stuff out.

Surprisingly, I just stumbled upon a thread that I made in the Spanish community "Whack a Hack!" where I reposted Ghoulslash's routine (giving all the credits to him, naturally.)
I also posted a script to get the routine working there, but instead of carelessly pasting it in Hastebin like I did here, I've put it in Pastebin.

Soo... yeah, here it is.
https://pastebin.com/2tv2QX18

AkameTheBulbasaur March 10th, 2019 2:06 PM

So because I have a life, I spent way too long yesterday writing a routine to change the measurements for the height and weight in the PokeDex to be in metric (for those who eschew the imperial system).

EDIT: I neglected to have this change the units for SEEN entries as well as CAUGHT entries. I fixed that now.


Height (Feet to Metres - (Uncaught Pokemon)):
Spoiler:
/* Assemble this at 0x1059D0 */
.text
.align 2
.thumb
.thumb_func

Main:
add r0, r13, #0xC
mov r1, #0xAC /* ? */
strb r1, [r0]
add r0, r0, #0x1
mov r1, #0xAC /* ? */
strb r1, [r0]
add r0, r0, #0x1
mov r1, #0x0 /* */
strb r1, [r0]
add r0, r0, #0x1
mov r1, #0xE1 /* m */
strb r1, [r0]
add r0, r0, #0x1
mov r1, #0xFF /* FF */
strb r1, [r0]
mov r0, r0
ldr r0, .Return
bx r0

.align 2
.Return: .word 0x081059FF


Height (Feet to Metres):
Spoiler:
/*00 48 00 47 XX XX XX 08 at 0x105924*/
.text
.align 2
.thumb
.thumb_func

/*r4 has the height number*/



Main:
mov r1, #0xB

Clear:
mov r2, r13
add r2, r2, r1
mov r0, #0x0
strb r0, [r2]
cmp r1, #0x10
beq Next
add r1, r1, #0x1
b Clear

Next:
mov r0, r4
cmp r4, #0xA
blt OneDigit
cmp r4, #0x64
blt TwoDigit

ThreeDigit:
mov r1, #0x64
bl Divide
mov r6, r0
mov r2, r13
add r2, r2, #0xC
mov r0, r6
add r0, r0, #0xA1
strb r0, [r2]
mul r1, r6
sub r0, r4, r1
mov r4, r0

TwoDigit:
mov r1, #0xA
bl Divide
mov r5, r0
mov r2, r13
add r2, r2, #0xD
mov r0, r5
add r0, r0, #0xA1
strb r0, [r2]
mul r1, r5
sub r0, r4, r1
mov r4, r0

OneDigit:
mov r2, r13
add r2, r2, #0xF
mov r0, r4
add r0, r0, #0xA1
strb r0, [r2]

PutTextIn:
mov r2, r13
add r2, r2, #0xE
mov r0, #0xAD
strb r0, [r2]
add r2, r2, #0x2
mov r0, #0x00
strb r0, [r2]
add r2, r2, #0x1
mov r0, #0xE1
strb r0, [r2]
add r2, r2, #0x1
mov r0, #0xFF
strb r0, [r2]
ldr r1, .Return
bx r1

Divide:
ldr r2, .Divide
bx r2

.align 2
.Return: .word 0x081059FF
.Divide: .word 0x081E4019


Weight (Pounds to Kilograms):
Spoiler:
/* 00 48 00 47 XX XX XX 08 at 0x105A94 */
/* Put AC 00 DF DB at 0x415FA0 */
.text
.align 2
.thumb
.thumb_func

/* r4 has the weight number */

Main:
mov r1, #0xB

Clear:
mov r2, r13
add r2, r2, r1
mov r0, #0x0
strb r0, [r2]
cmp r1, #0x10
beq Next
add r1, r1, #0x1
b Clear

Next:
mov r0, r4
cmp r4, #0xA
blt OneDigit
cmp r4, #0x64
blt TwoDigit
ldr r1, .Thousand
cmp r4, r1
blt ThreeDigit

FourDigit:
ldr r1, .Thousand
bl Divide
mov r6, r0
mov r2, r13
add r2, r2, #0xB
mov r0, r6
add r0, r0, #0xA1
strb r0, [r2]
ldr r1, .Thousand
mul r1, r6
sub r0, r4, r1
mov r4, r0

ThreeDigit:
mov r1, #0x64
bl Divide
mov r6, r0
mov r2, r13
add r2, r2, #0xC
mov r0, r6
add r0, r0, #0xA1
strb r0, [r2]
mov r1, #0x64
mul r1, r6
sub r0, r4, r1
mov r4, r0

TwoDigit:
mov r1, #0xA
bl Divide
mov r5, r0
mov r2, r13
add r2, r2, #0xD
mov r0, r5
add r0, r0, #0xA1
strb r0, [r2]
mov r1, #0xA
mul r1, r5
sub r0, r4, r1
mov r4, r0

OneDigit:
mov r2, r13
add r2, r2, #0xF
mov r0, r4
add r0, r0, #0xA1
strb r0, [r2]

PutTextIn:
mov r2, r13
add r2, r2, #0xE
mov r0, #0xAD
strb r0, [r2]
add r2, r2, #0x2
mov r0, #0x00
strb r0, [r2]
add r2, r2, #0x1
mov r0, #0xDF
strb r0, [r2]
add r2, r2, #0x1
mov r0, #0xDB
strb r0, [r2]
add r2, r2, #0x1
mov r0, #0x00
strb r0, [r2]
add r2, r2, #0x1
mov r0, #0xFF
strb r0, [r2]
ldr r1, .Return
bx r1

Divide:
ldr r2, .Divide
bx r2

.align 2
.Return: .word 0x08105BE7
.Divide: .word 0x081E4019
.Thousand: .word 0x000003E8

Cam March 28th, 2019 10:22 PM

>Ruby/Saphhire
>nothing to see here
Real disappointing considering I'm stuck with a ruby base for certain reasons.

Delta231 March 29th, 2019 5:03 AM

Quote:

Originally Posted by CloverDevteam (Post 9999147)
>Ruby/Saphhire
>nothing to see here
Real disappointing considering I'm stuck with a ruby base for certain reasons.

You can port some Routines if the functions are similar.

AtecainCorp. April 2nd, 2019 8:28 AM

Quote:

Originally Posted by Sagiri (Post 9947345)
Unhidden Power [FR]

This routine makes the game calculate and display the actual type of Hidden Power in battle and in status screens. If, for example, a Pok�mon's Hidden Power type is Water, it will display as a Water-type move, just like Surf or any other Water-type move.

https://github.com/Sagiri/unhidden-power/blob/master/in-battle.png?raw=true https://github.com/Sagiri/unhidden-power/blob/master/status-screen.png?raw=true

Note that this only calculates and displays the type, not the base power.

I try remade it for Ruby

PokemonXO April 6th, 2019 2:48 PM

Hello, I am looking to add battle items X Sp Def and X Evasion to the game (And perhaps, if it's workable, X HP)

I do not own IDA Pro, so it's going to be a real challenge trying to locate the correct offsets for the Battle Items. I don't know how it's done, but I guess I can request a tutorial here.

I will give credit when requested!

This is the location of the battle effect:

0FE4B9

ShinypikachuX April 11th, 2019 8:24 AM

I have a great idea for fire red I was thinking of in game player name change like to set the player name to a predefined name.
For example if the player name is David by setflag or setvar it could be changed to Mike I.e.,name decided by the hacker.
Sorry if this is too complicated and thanks in advance.

ghoulslash April 12th, 2019 6:26 AM

Quote:

Originally Posted by ShinypikachuX (Post 10004838)
I have a great idea for fire red I was thinking of in game player name change like to set the player name to a predefined name.
For example if the player name is David by setflag or setvar it could be changed to Mike I.e.,name decided by the hacker.
Sorry if this is too complicated and thanks in advance.

The player's name can be changed from the overworld via callasm 0x809FC91

I have a pretty old routine I wrote to change the OT name of your pokemon to the new name based on matching OTIDs, so traded pokemon will retain their OT names. Note that I wrote it a while ago so there may be bugs

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global ChangePokeNames
/*
Function to change all pokemon OT names to the players new name (unless IDs dont match aka traded pokemon)

Inputs:
        -none
Outputs:
        -none

Usage:
        callasm 0x809FC91  //rename player
        waitstate
        callasm [this_routine]+1
*/

Start:
        push {r0-r7, lr}

ChangePartyNames:
        ldr r7, .PartyPoke
        mov r6, #0x64
        mov r5, #0x5
        bl NameChanges

ChangeBoxNames:
        ldr r7, .BoxDMA
        ldr r7, [r7]
        add r7, #0x4
        mov r6, #0x50
        mov r5, #0x69
        lsl r5, r5, #0x2                @420 box pokemon total
        bl NameChanges

Exit:
        pop {r0-r7, pc}

/*
Name Change Call Function
        r5 = num pokes to check
        r6 = data size per poke
        r7 = start address
*/
NameChanges:
        push {lr}
        mov r4, #0x0       

OuterLoop:
        mov r0, r4
        mul r0, r6

GetPokeDataLoc:
        add r0, r0, r7
        ldrh r1, [r0, #0x4]       

GetPlayerID:
        ldr r2, .Saveblock
        ldr r3, [r2]
        ldrh r2, [r3, #0xA]       

CompareIDs:
        cmp r1, r2
        bne OuterLoopRestart                @OTIDs do not match -> no name change

PrepInnerLoop:
        add r0, #0x14
        mov r2, #0x0       

charLoop:
        ldrb r1, [r3]
        strb r1, [r0]
        cmp r2, #0x6                @7 bytes for OT name
        beq OuterLoopRestart
        add r3, #0x1
        add r0, #0x1
        add r2, #0x1
        b charLoop

OuterLoopRestart:
        cmp r4, r5
        beq Return
        add r4, #0x1
        b OuterLoop

Return:
        pop {r0}
        bx r0

.align 2
.PartyPoke:        .word 0x02024284
.Saveblock:        .word 0x0300500C
.BoxDMA:        .word 0x03005010



mattymannnn April 17th, 2019 9:28 AM

Does anyone know of a routine that blocks the user from releasing certain species of pokemon?

Super Versekr Dark April 17th, 2019 2:41 PM

Quote:

Originally Posted by Chacha Dinosaur (Post 8786554)
EV-enhancing items (Power Items)


Spoiler:


The routine now does not require any new Held Effect Item Byte. The new power items are tied to Macho Brace's Held Item Effect Byte. (Thanks to MrDollSteak for giving the idea.)
The type of EV gain is now differentiated by the Second Held Effect Byte (the byte just after the Primary Held Effect Byte in the Item Table).
There is no need to code the Speed Drop explicitly for Power Items.

Usage is now like this by using the following parameters in the Item Table:
Primary Byte | Secondary Byte | Item Name
0x18 | 0x0 | Macho Brace
0x18 | 0x1 | Power Weight
0x18 | 0x2 | Power Bracer
0x18 | 0x3 | Power Belt
0x18 | 0x4 | Power Anklet
0x18 | 0x5 | Power Lens
0x18 | 0x6 | Power Band

Also, there are additional byte changes mentioned in the Spoiler to limit the EVs for each stat from 255 to 252 to avoid wastage of EVs by normal battling.

Fire Red:-
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

Main:
    push {r2}
    mov r0, r8  /*Load pokemon slot no*/
    mov r1, #0xC
    mov r2, #0x0
    bl Decrypter /* Load pokemon's item */
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    pop {r2} /* Restore Pokerus Factor*/
    cmp r0, #0xAF
    beq EnigmaBerry
    add r3, r0, #0x0
    bl GetItemEffect /* Get Held Item's Effect Byte*/
    lsl r0, r0, #0x18
    lsr r0, r0, #0x18
    cmp r0, #0x18
    bne NoPowerItem
    add r0, r3, #0x0
    bl GetSecondEffectByte
    lsl r0, r0, #0x18
    lsr r0, r0, #0x18
    cmp r0, #0x0
    beq MachoBrace
    add r1, r6, #0x1 /*Load a Power Item's Secondary Effect Byte*/
    cmp r1, r0 /*Match items*/
    bne NoPowerItem /*No Power Item or No Match for that particular stat*/
    lsl r2, r2, #0x2
    add r4, r4, r2 /* Add 4 EVs or 8 (due to Pokerus) */
NoPowerItem:
    ldr r3, =0x080439D9
    bx r3

EnigmaBerry:
    ldr r3, =0x0804398F
    bx r3

MachoBrace:
    ldr r3, =0x080439D5
    bx r3

Decrypter:
    ldr r3, =0x0803FBE9
    bx r3

GetItemEffect:
    ldr r1, =0x0809A925
    bx r1

GetSecondEffectByte:
    ldr r1, =0x0809A949
    bx r1

/*At 43978: 04 1C 54 43 00 49 08 47 XX+1 XX XX 08 00 00 00 00 00 00 00 00 00 00*/
/*At 439FC && 43A02: FC to limit EV growth for each stat to 252 */




Emerald:-
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

Main:
    push {r2}
    mov r0, r8  /*Load pokemon slot no*/
    mov r1, #0xC
    mov r2, #0x0
    bl Decrypter /* Load pokemon's item */
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    pop {r2} /* Restore Pokerus Factor*/
    cmp r0, #0xAF
    beq EnigmaBerry
    add r3, r0, #0x0
    bl GetItemEffect /* Get Held Item's Effect Byte*/
    lsl r0, r0, #0x18
    lsr r0, r0, #0x18
    cmp r0, #0x18
    bne NoPowerItem
    add r0, r3, #0x0
    bl GetSecondEffectByte
    lsl r0, r0, #0x18
    lsr r0, r0, #0x18
    cmp r0, #0x0
    beq MachoBrace
    add r1, r6, #0x1 /*Load a Power Item's Secondary Effect Byte*/
    cmp r1, r0 /*Match items*/
    bne NoPowerItem /*No Power Item or No Match for that particular stat*/
    lsl r2, r2, #0x2
    add r4, r4, r2 /* Add 4 EVs or 8 (due to Pokerus) */
NoPowerItem:
    ldr r3, =0x0806DC25
    bx r3

EnigmaBerry:
    ldr r3, =0x0806DBDB
    bx r3

MachoBrace:
    ldr r3, =0x0806DC21
    bx r3

Decrypter:
    ldr r3, =0x0806A519
    bx r3

GetItemEffect:
    ldr r1, =0x080D74DD
    bx r1

GetSecondEffectByte:
    ldr r1, =0x080D7501
    bx r1

/*At 6DBC4: 04 1C 54 43 00 49 08 47 XX+1 XX XX 08 00 00 00 00 00 00 00 00 00 00*/
/*At 6DC48 && 6DC4E: FC to limit EV growth for each stat to 252 */





For Ruby:

Spoiler:
.text
.align 2
.thumb
.thumb_func

Main:
push {r2}
mov r0, r8 /*Load pokemon slot no*/
mov r1, #0xC
mov r2, #0x0
bl Decrypter /* Load pokemon's item */
lsl r0, r0, #0x10
lsr r0, r0, #0x10
pop {r2} /* Restore Pokerus Factor*/
cmp r0, #0xAF
beq EnigmaBerry
add r3, r0, #0x0
bl GetItemEffect /* Get Held Item's Effect Byte*/
lsl r0, r0, #0x18
lsr r0, r0, #0x18
cmp r0, #0x18
bne NoPowerItem
add r0, r3, #0x0
bl GetSecondEffectByte
lsl r0, r0, #0x18
lsr r0, r0, #0x18
cmp r0, #0x0
beq MachoBrace
add r1, r6, #0x1 /*Load a Power Item's Secondary Effect Byte*/
cmp r1, r0 /*Match items*/
bne NoPowerItem /*No Power Item or No Match for that particular stat*/
lsl r2, r2, #0x2
add r4, r4, r2 /* Add 4 EVs or 8 (due to Pokerus) */
NoPowerItem:
ldr r3, =0x0803FFB9
bx r3

EnigmaBerry:
ldr r3, =0x0803FF6F
bx r3

MachoBrace:
ldr r3, =0x0803FFB5
bx r3

Decrypter:
ldr r3, =0x0803CB61
bx r3

GetItemEffect:
ldr r1, =0x080A993D
bx r1

GetSecondEffectByte:
ldr r1, =0x080A9961
bx r1

/*At 3FF58: 04 1C 54 43 00 49 08 47 XX+1 XX XX 08 00 00 00 00 00 00 00 00 00 00*/
/*At 3FFDC && 3FFE2: FC to limit EV growth for each stat to 252 */

ShinypikachuX April 18th, 2019 9:52 AM

Quote:

Originally Posted by ghoulslash (Post 10005286)
The player's name can be changed from the overworld via callasm 0x809FC91

I have a pretty old routine I wrote to change the OT name of your pokemon to the new name based on matching OTIDs, so traded pokemon will retain their OT names. Note that I wrote it a while ago so there may be bugs

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global ChangePokeNames
/*
Function to change all pokemon OT names to the players new name (unless IDs dont match aka traded pokemon)

Inputs:
        -none
Outputs:
        -none

Usage:
        callasm 0x809FC91  //rename player
        waitstate
        callasm [this_routine]+1
*/

Start:
        push {r0-r7, lr}

ChangePartyNames:
        ldr r7, .PartyPoke
        mov r6, #0x64
        mov r5, #0x5
        bl NameChanges

ChangeBoxNames:
        ldr r7, .BoxDMA
        ldr r7, [r7]
        add r7, #0x4
        mov r6, #0x50
        mov r5, #0x69
        lsl r5, r5, #0x2                @420 box pokemon total
        bl NameChanges

Exit:
        pop {r0-r7, pc}

/*
Name Change Call Function
        r5 = num pokes to check
        r6 = data size per poke
        r7 = start address
*/
NameChanges:
        push {lr}
        mov r4, #0x0       

OuterLoop:
        mov r0, r4
        mul r0, r6

GetPokeDataLoc:
        add r0, r0, r7
        ldrh r1, [r0, #0x4]       

GetPlayerID:
        ldr r2, .Saveblock
        ldr r3, [r2]
        ldrh r2, [r3, #0xA]       

CompareIDs:
        cmp r1, r2
        bne OuterLoopRestart                @OTIDs do not match -> no name change

PrepInnerLoop:
        add r0, #0x14
        mov r2, #0x0       

charLoop:
        ldrb r1, [r3]
        strb r1, [r0]
        cmp r2, #0x6                @7 bytes for OT name
        beq OuterLoopRestart
        add r3, #0x1
        add r0, #0x1
        add r2, #0x1
        b charLoop

OuterLoopRestart:
        cmp r4, r5
        beq Return
        add r4, #0x1
        b OuterLoop

Return:
        pop {r0}
        bx r0

.align 2
.PartyPoke:        .word 0x02024284
.Saveblock:        .word 0x0300500C
.BoxDMA:        .word 0x03005010



No no I want to set player name to another one without any freedom to player, so I decide the name not the player.
But thanks anyways.
By the way can you help me I'm stuck with the random trainer id and secret id generator routine it won't compile for me please help.

kevvic April 24th, 2019 1:52 AM

Quote:

Originally Posted by Lunos (Post 9972821)
I
EDIT:

I was testing this routine out just now, and I'm not entirely sure if it's working correctly.
It looks to me like the Eggs are inheriting 3 stats alone, when they should always inherit 5 stats :/
I've been doing tests using this routine and XXXX.

In my last attempt for example, the results of the Egg were:
-03 HP IVs. Charmander has 30 and Ditto 26.
-03 Atk IVs inherited from Charmander.
-22 Def IVs inherited from Charmander or Ditto (both have 22 Def IVs.)
-23 Spd IVs. Charmander has 31 and Ditto 25.
-19 SpAtk IVs. Charmander has 31 and Ditto 10.
-31 SpDef IVs inherited from Ditto.

If we assume that HP is the random stat in this spread, Spd and SpAtk are the issue here.
The Egg should have inherited Charmander's or Ditto's values in those stats after all, right?
Has anyone tested this yet?

I did, I checked IV with the IV display summary screen routines. I edited the save so both parents have 31 IV in all stats, yet the child only have 3 stats with 31 IV.

Also for some reasons, sometimes if I give the destiny knot to the other parent or to both it crash when I talk to get the eggs. Did you figure it out?

ghoulslash April 25th, 2019 11:33 AM

Quote:

Originally Posted by ShinypikachuX (Post 10007751)
No no I want to set player name to another one without any freedom to player, so I decide the name not the player.
But thanks anyways.
By the way can you help me I'm stuck with the random trainer id and secret id generator routine it won't compile for me please help.

Actually, that's much easier. This will let you load a new player name into loadpointer 0x0 and then force the change. Make sure the player's name is 7 characters or less or else it will fail.
Spoiler:

Code:

.text
.align 2
.thumb
.global NewPlayerName
/*
usage:
        loadpointer 0x0 @name
        callasm [this_routine+1]
*/

Main:
        push {r0-r4, lr}
        ldr r0, .loadPointer
        ldr r0, [r0]    @string pointer
        mov r4, r0
        bl StringLength
        cmp r0, #0x7
        bgt Exit
        ldr r0, .TrainerDMA
        ldr r0, [r0]        @dest
        mov r1, r4                @src
        bl StringCopy
Exit:
        pop {r0-r4, pc}

StringLength:
        ldr r1, =(0x8008E08|1)
        bx r1

StringCopy:
        ldr r2, =(0x8008D84|1)
        bx r2

.align 2
.loadPointer: .word 0x03000f14
.TrainerDMA: .word 0x0300500c




eg. if I insert the above at 0x990000, then in XSE I could do the following to force the player's name to be Fred.
Code:

#dynamic 0x800000
#org @start
lock
faceplayer
loadpointer 0x0 @name
callasm 0x8990001
msgbox @newName 0x6
release
end
#org @name
= Fred
#org @newName
= Your new name is [player]!


Quote:

By the way can you help me I'm stuck with the random trainer id and secret id generator routine it won't compile for me please help.
I'm not sure what routine you're talking about, sorry :/

ShinypikachuX April 26th, 2019 10:57 AM

Quote:

Originally Posted by ghoulslash (Post 10010682)
Actually, that's much easier. This will let you load a new player name into loadpointer 0x0 and then force the change. Make sure the player's name is 7 characters or less or else it will fail.
Spoiler:

Code:

.text
.align 2
.thumb
.global NewPlayerName
/*
usage:
        loadpointer 0x0 @name
        callasm [this_routine+1]
*/

Main:
        push {r0-r4, lr}
        ldr r0, .loadPointer
        mov r4, r0
        bl StringLength
        cmp r0, #0x7
        bgt Exit
        ldr r0, .TrainerDMA
        ldr r0, [r0]        @dest
        mov r1, r4                @src
        bl StringCopy
Exit:
        pop {r0-r4, pc}

StringLength:
        ldr r1, =(0x8008E08|1)
        bx r1

StringCopy:
        ldr r2, =(0x8008D84|1)
        bx r2

.align 2
.loadPointer: .word 0x03000f14
.TrainerDMA: .word 0x0300500c




eg. if I insert the above at 0x990000, then in XSE I could do the following to force the player's name to be Fred.
Code:

#dynamic 0x800000
#org @start
lock
faceplayer
loadpointer 0x0 @name
callasm 0x8990001
msgbox @newName 0x6
release
end
#org @name
= Fred
#org @newName
= Your new name is [player]!



I'm not sure what routine you're talking about, sorry :/

Thanks for this quick response and for the routine not tried it yet though.
The routine I was talking about is this http://www.pokecommunity.com/showpost.php?p=8536952&postcount=333

TheWolfProd April 26th, 2019 12:30 PM

Quote:

Originally Posted by ghoulslash (Post 10010682)
Actually, that's much easier. This will let you load a new player name into loadpointer 0x0 and then force the change. Make sure the player's name is 7 characters or less or else it will fail.
Spoiler:

Code:

.text
.align 2
.thumb
.global NewPlayerName
/*
usage:
        loadpointer 0x0 @name
        callasm [this_routine+1]
*/

Main:
        push {r0-r4, lr}
        ldr r0, .loadPointer
        mov r4, r0
        bl StringLength
        cmp r0, #0x7
        bgt Exit
        ldr r0, .TrainerDMA
        ldr r0, [r0]        @dest
        mov r1, r4                @src
        bl StringCopy
Exit:
        pop {r0-r4, pc}

StringLength:
        ldr r1, =(0x8008E08|1)
        bx r1

StringCopy:
        ldr r2, =(0x8008D84|1)
        bx r2

.align 2
.loadPointer: .word 0x03000f14
.TrainerDMA: .word 0x0300500c




eg. if I insert the above at 0x990000, then in XSE I could do the following to force the player's name to be Fred.
Code:

#dynamic 0x800000
#org @start
lock
faceplayer
loadpointer 0x0 @name
callasm 0x8990001
msgbox @newName 0x6
release
end
#org @name
= Fred
#org @newName
= Your new name is [player]!



I'm not sure what routine you're talking about, sorry :/

I tried running this script with the same offsets in FireRed but when I go to speak to the NPC i assigned the script to the game freezes. Is there something I could've missed? I compiled the ASM, assigned the correct offsets in the hex editior. Thankyou:)

ShinypikachuX April 28th, 2019 5:10 AM

Someone help like all the asm routine I compile won't work for some god damn reason someone reply if you know how to fix this and if you post a compiler which works for you it would be more helpful.

Diego98 May 13th, 2019 11:23 AM

Quote:

Originally Posted by Koople (Post 9924710)
Side Quest Menu [FR]

This hack converts the PC item storage menu into a side quest menu, or task list, etc.

Here is the repository, the compilation instructions are included in the readme. You will need to define your own parameters/ram in src/headers/defs.asm and create your own tables of string pointers for all of the quest names, descriptions, item images, and quest details. I kept the item image part to allow hackers to include items that might be symbolic of their quest, eg. a scroll or key or pokeball.

To use in a script (XSE)
Code:

writebytetooffset 0x1 <your questflag ram in src/headers/defs.asm>
fadescreen 0x1
callasm 0x80EBCD9
waitstate


Enjoy! And please let me know of any bugs.

I'm trying to build that but I'm getting an error code:
Code:

arm-none-eabi-as -mthumb -c src/quest_select_msg.asm -o build/src/quest_select_msg.o
make: arm-none-eabi-as: Command not found
make: *** [makefile:17: build/src/quest_select_msg.o] Error 127


I built lots of other things but never got this error. What should I do?

EDIT: Ok, forgot it. It was a typing mistake on my system path to the DevkitARM bin folder.

Diego98 May 19th, 2019 11:02 AM

I'm searching for a routine that opens the bag to select an item (like when you give some item to a pokemon from the pokemon menu) and it saves the item ID into a variable. Does anyone know something about it or how to do it?

mattymannnn May 19th, 2019 11:16 AM

Quote:

Originally Posted by Diego98 (Post 10021284)
I'm searching for a routine that opens the bag to select an item (like when you give some item to a pokemon from the pokemon menu) and it saves the item ID into a variable. Does anyone know something about it or how to do it?

https://www.pokecommunity.com/showthread.php?t=295749

Diego98 May 19th, 2019 1:23 PM

Quote:

Originally Posted by mattymannnn (Post 10021298)

Great! That's just what I needed

Dragoonite May 24th, 2019 3:02 PM

Would it be possible to remove the character and rival naming process and make them both a set name in FireRed?

Spherical Ice May 29th, 2019 6:01 AM

[FR] Switch the title screen's "Charizard" tilemap based on a flag



Code:

.thumb

.equ rom, 0x08000000
.equ free_space, 0x
.equ title_screen_default_palette, 0xEAD5E8 @ these are the default for FireRed's Charizard tilemap
.equ title_screen_default_tileset, 0xEAD608
.equ title_screen_default_tilemap, 0xEADEE4
.equ title_screen_new_palette, 0x
.equ title_screen_new_tileset, 0x
.equ title_screen_new_tilemap, 0x
.equ new_flag, 0x

.org 0x78A1A, 0xFF
hook:
    ldr r0, =(rom + main + 1)
    bx r0
.pool

.org 0x78F62, 0xFF
hook1:
    ldr r0, =(rom + main1 + 1)
    bx r0
.pool

.org 0x79670, 0xFF
hook2:
    ldr r0, =(rom + main2 + 1)
    bx r0
.pool

.org free_space, 0xFF
main:
    push {r5}
    mov r5, r4

    ldr r0, =new_flag
    bl flag_check
    cmp r0, #1
    beq new

default:
    ldr r0, =(rom + title_screen_default_palette)
    mov r1, #0xD0
    mov r2, #0x20
    bl gpu_pal_apply

    ldr r1, =(rom + title_screen_default_tileset)
    str r4, [sp]
    mov r0, #1
    mov r2, #0
    mov r3, #0
    bl decompress_with_fallback_maybe

    ldr r1, =(rom + title_screen_default_tilemap)
    b continue

new:
    ldr r0, =(rom + title_screen_new_palette)
    mov r1, #0xD0
    mov r2, #0x20
    bl gpu_pal_apply

    ldr r1, =(rom + title_screen_new_tileset)
    str r4, [sp]
    mov r0, #1
    mov r2, #0
    mov r3, #0
    bl decompress_with_fallback_maybe

    ldr r1, =(rom + title_screen_new_tilemap)

continue:
    str r6, [sp]
    mov r0, #1
    mov r2, #0
    mov r3, #0
    bl decompress_with_fallback_maybe

    mov r4, r5
    pop {r5}
    ldr r0, =(rom + 0x78a40 + 1)
    bx r0

.pool

main1:
    ldr r0, =new_flag
    bl flag_check
    cmp r0, #1
    beq new1

default1:
    ldr r0, =(rom + title_screen_default_palette)
    b continue1

new1:
    ldr r0, =(rom + title_screen_new_palette)

continue1:
    ldr r1, =0x2037398
    mov r2, #0x10
    bl CpuSet
    mov r0, #0x2
    lsl r0, r0, #0xC
    str r5, [sp]
    str r7, [sp, #4]
    str r7, [sp, #4]
    ldr r1, =(rom + 0x78f76 + 1)
    bx r1

.pool

main2:
    ldr r0, =new_flag
    bl flag_check
    cmp r0, #1
    beq new2

default2:
    ldr r0, =(rom + title_screen_default_palette)
    b continue2

new2:
    ldr r0, =(rom + title_screen_new_palette)

continue2:
    mov r1, #0xD0
    mov r2, #0x20
    bl gpu_pal_apply

    ldr r4, =(rom + 0x7967a + 1)
    bx r4

.pool

gpu_pal_apply:
    ldr r3, =(rom + 0x703EC + 1)
    bx r3

flag_check:
    ldr r1, =(rom + 0x6E6D0 + 1)
    bx r1

decompress_with_fallback_maybe:
    ldr r4, =(rom + 0xF6878 + 1)
    bx r4

CpuSet:
    ldr r3, =(rom + 0x1E3B64 + 1)
    bx r3

.pool


Pretty easily extendible for more than 2 different ones, if you swap out the flag for a variable (obviously assuming you have some ASM fluency).

/JASHIN/ June 6th, 2019 2:54 PM

Quote:

Originally Posted by daniilS (Post 8513264)
Actually, I wouldn't recommend using JPAN's method: for some reason he wrote a completely custom decryptor, while there is an existing one in the rom already. It's way easier to use because changing a pokémon's species requires just a single callasm. (If anybody is interested, I made this in ancient times: )
Spoiler:
Code:

.text
.align 2
.thumb
.thumb_func
.global Indexnumber_changeand20bytes_recalc

main:
        push {r0-r3, lr}
getpokeoffset:
        ldr r0, varnumber_8004
        ldr r3, vardecrypt
        bl bxr3
        ldrh r2, [r0]
        mov r0, #100
        mul r2, r0
        ldr r0, partystart
        add r3, r2, r0
        push {r3}
getandsetnewindexnumber:
        ldr r0, vartocontainnewindexnumber
        ldr r3, vardecrypt
        bl bxr3
        mov r2, r0
        mov r1, #0xB
        ldr r0, [sp]
        ldr r3, pokeencrypt
        bl bxr3
recalc20bytes:
        pop {r0}
        ldr r3, effectivestatsrecalc
        bl bxr3
        pop {r0-r3, pc}
bxr3:
        bx r3

.align 2
        varnumber_8004:                        .word 0x8004
        vardecrypt:                        .word 0x0806E454+1
        partystart:                        .word 0x02024284
        vartocontainnewindexnumber:        .word 0x8005
        pokeencrypt:                        .word 0x0804037C+1
        effectivestatsrecalc:                .word 0x0803e47c+1

/*Insert anywhere. then use special 0x9F to select a pokemon, waitstate, setvar 0x8005 to the desired index number, and callasm this routine+1*/




However, I believe the thing that's important about his request is playing the evolution animation, which isn't as easy to do as this.

My question regarding this how can I make it so that not every pokemon that is picked can change into the form?
Also, I noticed that when you change forms it changes the pokemon's level to be one less than it was before.

/JASHIN/ June 6th, 2019 2:58 PM

Quote:

Originally Posted by FBI (Post 8514208)
I just copy-pasted and compiled it with no problems.

usage:

So if I wanted to evolve the 3rd Pokemon in my party I would put:
setvar 0x8001 0x2
callasm 0xOffset +1

Here's a compiled version:
Code:

FF B5 49 48 00 88 64 21 48 43 48 49 40 18 07 1C 0B 21 47 4B 00 F0 84 F8 05 1C 00 F0 29 F8 06 1C 38 1C 38 21 42 4B 00 F0 7B F8 04 1C 38 1C 3D 4A 31 1C 11 80 0B 21 3F 4B 00 F0 72 F8 38 1C 3E 4B 00 F0 6E F8 30 1C 3D 4B 00 F0 6A F8 30 1C 02 21 3B 4B 00 F0 65 F8 30 1C 03 21 39 4B 00 F0 60 F8 38 1C 38 21 32 4B 00 F0 5B F8 A0 42 37 D1 0C E0 04 21 41 43 40 18 C0 00 32 4B C1 18 48 88 8A 88 90 42 00 DC 70 47 10 1C 70 47 38 1C 2E 49 0A 1C 02 21 27 4B 00 F0 44 F8 2C 48 0B 21 69 43 09 18 0D 1C 29 49 0C 1C 00 20 0A 28 0D D0 01 35 29 78 01 34 22 78 8A 42 32 D1 FF 2A 00 D0 02 E0 FF 29 02 D0 2C E0 01 30 EF E7 20 4A 0B 20 46 43 B6 18 38 1C 32 1C 02 21 17 4B 00 F0 22 F8 1F E0 A0 42 D3 D0 02 1C 38 1C 19 21 11 4B 00 F0 19 F8 01 1C 00 09 A2 42 01 D9 09 18 00 E0 09 1A 09 4A 11 60 19 21 38 1C 0B 4B 00 F0 0B F8 38 1C 0A 4B 00 F0 07 F8 38 1C 38 21 06 4B 00 F0 02 F8 DF E7 FF BD 18 47 C0 46 B8 70 03 02 BA 70 03 02 84 42 02 02 E9 FB 03 08 7D 03 04 08 7D E4 03 08 99 32 04 08 75 8E 08 08 54 97 25 08 D0 1C 02 02 E0 5E 24 08



So let's say I wanted to make Deoxys "evolve" into another form of Deoxys when I talk to a meteor. How would I go about making the "evolve" Deoxys specifically whether it is in slot 1 or 3 or 5, etc?

/JASHIN/ June 6th, 2019 4:59 PM

Quote:

Originally Posted by jiangzhengwenjzw (Post 9229108)
Misc:

Evolution via Callasm in FR


Spoiler:
I will show you the GIF result of the hack:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/Untitled_zpsklaexwbz.gif
Firstly, we just insert a function at 0xYYYYYY:
Code:

.thumb
push {r4, lr}
ldr r0, =0x300537C
ldr r1, =0x80568E1
str r1, [r0]
ldr r0, =0x020370C0
ldrh r1, [r0, #2]
mov r2, #1
ldrh r3, [r0, #0x10]
ldr r4, =0x80cdda9
bl bx_r4
pop {r4, pc}
bx_r4: bx r4


After that we should insert another function at 0xZZZZZZ:
Code:

.thumb
push {r4, lr}
mov r4, #0
loop:
ldr r0, =0x02024284
mov r1, #0x64
mul r1, r4
add r0, r0, r1
mov r1, #0xb
ldr r2, =0x803FBE9
bl bx_r2
ldr r1, =0x20370C0
ldrh r2, [r1]
cmp r0, r2
beq have_pre
add r4, #1
cmp r4, #6
bne loop

no_pokemon:
mov r4, #0xFF
b back

increment:
add r4, #1
cmp r4, #6
beq no_pokemon
b loop

have_pre:
ldr r0, =0x2024284
mov r1, #0x64
mul r1, r4
add r0, r0, r1
mov r1, #0x2d
ldr r2, =0x803FBE9
bl bx_r2
ldr r1, =0x20370C0
cmp r0, #1
beq increment

back:
strh r4, [r1, #0x10]
pop {r4, pc}
bx_r2:
bx r2


To use it via a script:
Code:

#org @start
lock
faceplayer
setvar 0x8004 0x4 //the species number of pokemon you want it to evolve(here's chamander)
setvar 0x8005 0x2 //the species number of pokemon after evolution(here's ivysaur)
callasm 0x8ZZZZZZ+1 //check the slot number of the pokemon
compare 0x800D 0xFF //check if the pokemon exists in the player's party
if1 1 @no_that_pokemon
callasm 0x8YYYYYY+1 //evolution
waitstate
//setweather 3 //you can define other events after waitstate
//doweather
release
end

//---------------
#org @no_that_pokemon
msgbox @message_string 6 //"You don't have that pokemon. "
release
end

//---------
// Strings
//---------
#org @message_string
= You don't have that pokemon.


Note: Only the first pokemon in your party with the species number in 0x8004 will evolve. I think that's better.

A EV-IV Display Screen


RENEWAL:
Spoiler:
The new version is here (no difference, but codes will be automatically inserted into the ROM):
FIRERED:
https://github.com/jiangzhengwenjz/EV-IV-Screen
EMERALD:
https://github.com/jiangzhengwenjz/EV-IV-Screen-EM
Read Readme.md to know how to compile.

Quick Preview:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/q_zpshnquzant.gifhttps://i.imgur.com/18HjHg0.png

OLD CONTENT:
Spoiler:
Quick Preview:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/q_zpshnquzant.gif
Download:
https://github.com/jiangzhengwenjz/EV-IV-Screen/tree/c1b303e17788f21e1a663204f9db59ffdcfc2a2d
Usage:
1. Make sure that you have Devkitarm and GNU make/cygwin installed.
2. Download this repo and create a new folder called "build".
3. Assign the free space you want to use in linker.lsc.
4. Open your cmd prompt and type in make. Then press enter.
5. Now main.bin should be generated. Paste it to the offset specified in step3.
6. Write a script to test (You should callasm to the offset of insertion + 0x79).
Code:

Example:
lock
faceplayer
callasm 0x8800079 //I inserted the code at 0x8800000
msgbox 0x8FD0013 0x2 //"It's nice, huh?"
releaseall
end



80x80 mugshots


Spoiler:
Intro:
In Ruby, many hackers uses the BG0 to make mugshots. However, the same way that simply writing tileset, tilemap and palette to the RAM won't work for FR & EM as it will be cleared by the MSGBOX.

However, there's still a way to do it, which requires the knowledge of "rboxes". I've figured out some simple usage of the related functions, so I will show you my work:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/1636%20-%20Pokemon%20-%20Fire%20Red%20Version_zpsryxoq5ye.png

The most ****ing thing should be that only 1 BG palette for FR can be used, which is the palette for the money box (the box with thinner border). Therefore, it will only be able to launch 1 mugshot at a time and you can't use it with the money box!

How to use:
The routines are provided at the bottom.
1. Change 0x8900000 in mugshot_make.asm to free space, which is ended in 0,4,8,c. It will be the location of our custom table.
2. Compile the 2 routines and insert them to some free space (Not the table location in step 1)
3. Get/draw some 80x80 mugshots, here's 2 examples:
http://i.imgur.com/8Z0ppvU.pnghttp://i.imgur.com/5bRm9Vg.png
They should be indexed to 16 colors.
4. Open your UNLZ-GBA and insert your images and palettes.
Note: the image and the palette should all be LZ77 compressed, which means that you should insert them by using "export image" and "export palette" in UNLZ-GBA. Aparrently they should all be inserted at some free space.
5. Build the table at the offset in step 1, whose format should be [image0 pointer][image0 pal pointer][image1 pointer][image1 pal pointer][image2 pointer][image2 pal pointer]...................
It can load up to 65536 images in algorithm, which means that it's enough.
6. Test time! use
setvar 0x8004 [image index in the table]
setvar 0x8005 [0 or 1] // 0 = left, 1 = right
callasm 0x8[mugshot_make.asm+1]
to launch the mugshot and
callasm 0x8[mugshot_del.asm+1] to delete it.

An example:
I insert the 2 images at 0xFA0000, 0xFA09CC and the 2 palettes at 0xFA09A4, 0xFA1484. Then the table should be:
Code:

00 00 FA 08 A4 09 FA 08 CC 09 FA 08 84 14 FA 08


The script:
Code:

//---------------
#org 0xF00000
lock
setvar 0x8004 0x0 //image0
setvar 0x8005 0x1 //right side
callasm 0x8800001 //mugshot_make.asm+1
msgbox 0x8F00030 0x6
callasm 0x8800089 //mugshot_del.asm+1
release
end

#org 0xF00030
= ABCD.


The routines:
mugshot_make.asm:
Code:

/*
Note: both image and palette should be LZ77 compressed!
Table format: [image pointer][pal pointer]..........
*/
.equiv table_location, 0x8900000
.thumb
push {r4-r5, lr}
sub sp, sp, #0x18
ldr r0, =0x20370C0
ldrh r0, [r0, #2]
mov r1, #0
mov r2, #0x14
mul r2, r0
mov r3, #4
mov r0, #10
str r0, [sp]
str r0, [sp, #4]
mov r0, #0xD
str r0, [sp, #8]
mov r0, #0x40
str r0, [sp, #0xC]
add r0, sp, #0x10
ldr r4, =0x810FE51
bl bx_r4
add r0, sp, #0x10
ldr r4, =0x8003CE5
bl bx_r4
ldr r4, =0x2039990
strb r0, [r4]
ldr r4, =0x8003FA1
bl bx_r4
ldr r0, =0x20370C0
ldrh r0, [r0]
ldr r1, =table_location
lsl r0, r0, #3
add r0, r0, r1
ldr r5, [r0, #4]
ldr r0, [r0]
ldr r1, =0x6008800
swi 0x12
mov r0, r5
mov r1, #0xd0
mov r2, #0x20
ldr r4, =0x80703A9
bl bx_r4
mov r0, #0
ldr r4, =0x80020BD
bl bx_r4
add sp, sp, #0x18
pop {r4-r5, pc}

bx_r4: bx r4


mugshot_del.asm:
Code:

.thumb
push {r4, lr}
ldr r4, =0x2039990
ldrb r4, [r4]
mov r1, #0
mov r0, r4
ldr r3, =0x810F4D9
bl bx_r3
mov r0, r4
mov r1, #2
ldr r3, =0x8003F21
bl bx_r3
mov r0, r4
ldr r3, =0x8003E3D
bl bx_r3
pop {r4, pc}

bx_r3: bx r3



Some new movement bytes (including a patch)


Spoiler:
The patch will write new data to the offset 0xF80000, so make sure that area of your hack has not been used yet. Here's the download link:
http://www.mediafire.com/download/hfb2s47jq3k4oow/movements.ips

I haven't tested much on this hack, so it may have some bugs but you can modify it on your own as I've released the source code at the bottom.

The new bytes are:
Code:

0xAA - move up backwards (very slow)
0xAB - move down backwards (very slow)
0xAC - move right backwards (very slow)
0xAD - move left backwards (very slow)
0xAE - move up backwards (slow)
0xAF - move down backwards (slow)
0xB0 - move right backwards (slow)
0xB1 - move left backwards (slow)
0xB2 - move up backwards (normal)
0xB3 - move down backwards (normal)
0xB4 - move right backwards (normal)
0xB5 - move left backwards (normal)
0xB6 - move up backwards (fast)
0xB7 - move down backwards (fast)
0xB8 - move right backwards (fast)
0xB9 - move left backwards (fast)
0xBA - jump up backwards (2 squares)
0xBB - jump down backwards (2 squares)
0xBC - jump right backwards (2 squares)
0xBD - jump left backwards (2 squares)
0xBE - jump up backwards (1 square)
0xBF - jump down backwards (1 square)
0xC0 - jump right backwards (1 square)
0xC1 - jump left backwards (1 square)
0xC2 - face down and move left-down (normal)
0xC3 - face up and move left-up (normal)
0xC4 - face left and move left-down (normal)
0xC5 - face right and move right-down (normal)
0xC6 - face down and move right-down (normal)
0xC7 - face up and move right-up (normal)
0xC8 - face left and move left-up (normal)
0xC9 - face right and move right-up (normal)


Here's a picture including all the bytes above in a script:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/1_zps4xafcixu.gif

The diagonal ones (0xc2~0xc9) can be used in some kind of stairs, as [MENTION=26643]Invert[/MENTION] asked of me about that kind of stairs.

Some people may be interested in the source code, so I will put it here:
Code:

.equ ins_ofs, 0x8F802A8
.thumb
.align 2
table_expansion:
.word ins_ofs+walk_ldmu, ins_ofs+walk_lumd, ins_ofs+walk_llmr, ins_ofs+walk_lrml
.word ins_ofs+go_ldmu, ins_ofs+go_lumd, ins_ofs+go_llmr, ins_ofs+go_lrml
.word ins_ofs+pulse_ldmu, ins_ofs+pulse_lumd, ins_ofs+pulse_llmr, ins_ofs+pulse_lrml
.word ins_ofs+run_ldmu, ins_ofs+run_lumd, ins_ofs+run_llmr, ins_ofs+run_lrml
.word ins_ofs+jump_2sq_ldmu, ins_ofs+jump_2sq_lumd, ins_ofs+jump_2sq_llmr, ins_ofs+jump_2sq_lrml
.word ins_ofs+jump_1sq_ldmu, ins_ofs+jump_1sq_lumd, ins_ofs+jump_1sq_llmr, ins_ofs+jump_1sq_lrml
.word ins_ofs+pulse_15, ins_ofs+pulse_27, ins_ofs+pulse_35, ins_ofs+pulse_46
.word ins_ofs+pulse_16, ins_ofs+pulse_28, ins_ofs+pulse_37, ins_ofs+pulse_48

walk_ldmu: .word ins_ofs+walk_ldmu_func+1, ins_ofs+an_walk_dn_2+1, 0x8067935
walk_lumd: .word ins_ofs+walk_lumd_func+1, ins_ofs+an_walk_dn_2+1, 0x8067935
walk_llmr: .word ins_ofs+walk_llmr_func+1, ins_ofs+an_walk_dn_2+1, 0x8067935
walk_lrml: .word ins_ofs+walk_lrml_func+1, ins_ofs+an_walk_dn_2+1, 0x8067935

go_ldmu: .word ins_ofs+go_ldmu_func+1, ins_ofs+an_go_dn_2+1, 0x8067935
go_lumd: .word ins_ofs+go_lumd_func+1, ins_ofs+an_go_dn_2+1, 0x8067935
go_llmr: .word ins_ofs+go_llmr_func+1, ins_ofs+an_go_dn_2+1, 0x8067935
go_lrml: .word ins_ofs+go_lrml_func+1, ins_ofs+an_go_dn_2+1, 0x8067935

pulse_ldmu: .word ins_ofs+pulse_ldmu_func+1, ins_ofs+an_pulse_dn_2+1, 0x8067935
pulse_lumd: .word ins_ofs+pulse_lumd_func+1, ins_ofs+an_pulse_dn_2+1, 0x8067935
pulse_llmr: .word ins_ofs+pulse_llmr_func+1, ins_ofs+an_pulse_dn_2+1, 0x8067935
pulse_lrml: .word ins_ofs+pulse_lrml_func+1, ins_ofs+an_pulse_dn_2+1, 0x8067935

run_ldmu: .word ins_ofs+run_ldmu_func+1, ins_ofs+an_run_dn_2+1, 0x8067935
run_lumd: .word ins_ofs+run_lumd_func+1, ins_ofs+an_run_dn_2+1, 0x8067935
run_llmr: .word ins_ofs+run_llmr_func+1, ins_ofs+an_run_dn_2+1, 0x8067935
run_lrml: .word ins_ofs+run_lrml_func+1, ins_ofs+an_run_dn_2+1, 0x8067935

jump_2sq_ldmu: .word ins_ofs+jump_2sq_ldmu_func+1, ins_ofs+an_jump_2sq_dn_2+1, 0x8067935
jump_2sq_lumd: .word ins_ofs+jump_2sq_lumd_func+1, ins_ofs+an_jump_2sq_dn_2+1, 0x8067935
jump_2sq_llmr: .word ins_ofs+jump_2sq_llmr_func+1, ins_ofs+an_jump_2sq_dn_2+1, 0x8067935
jump_2sq_lrml: .word ins_ofs+jump_2sq_lrml_func+1, ins_ofs+an_jump_2sq_dn_2+1, 0x8067935

jump_1sq_ldmu: .word ins_ofs+jump_1sq_ldmu_func+1, ins_ofs+an_jump_1sq_dn_2+1, 0x8067935
jump_1sq_lumd: .word ins_ofs+jump_1sq_lumd_func+1, ins_ofs+an_jump_1sq_dn_2+1, 0x8067935
jump_1sq_llmr: .word ins_ofs+jump_1sq_llmr_func+1, ins_ofs+an_jump_1sq_dn_2+1, 0x8067935
jump_1sq_lrml: .word ins_ofs+jump_1sq_lrml_func+1, ins_ofs+an_jump_1sq_dn_2+1, 0x8067935

pulse_15: .word ins_ofs+pulse_15_func+1, ins_ofs+pulse15_func_2+1, 0x8067935
pulse_27: .word ins_ofs+pulse_27_func+1, ins_ofs+pulse15_func_2+1, 0x8067935
pulse_35: .word ins_ofs+pulse_35_func+1, ins_ofs+pulse15_func_2+1, 0x8067935
pulse_46: .word ins_ofs+pulse_46_func+1, ins_ofs+pulse15_func_2+1, 0x8067935
pulse_16: .word ins_ofs+pulse_16_func+1, ins_ofs+pulse16_func_2+1, 0x8067935
pulse_28: .word ins_ofs+pulse_28_func+1, ins_ofs+pulse16_func_2+1, 0x8067935
pulse_37: .word ins_ofs+pulse_37_func+1, ins_ofs+pulse16_func_2+1, 0x8067935
pulse_48: .word ins_ofs+pulse_48_func+1, ins_ofs+pulse16_func_2+1, 0x8067935

pulse_15_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #1
mov r3, #0
bl an_run_any_f
mov r0, r4
mov r1, r5
bl pulse15_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_27_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #2
mov r3, #0
bl an_run_any_f
mov r0, r4
mov r1, r5
bl pulse15_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_35_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #3
mov r3, #0
bl an_run_any_f
mov r0, r4
mov r1, r5
bl pulse15_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_46_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #4
mov r3, #0
bl an_run_any_f
mov r0, r4
mov r1, r5
bl pulse15_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_16_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #1
mov r3, #0
bl an_run_any_g
mov r0, r4
mov r1, r5
bl pulse16_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_28_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #2
mov r3, #0
bl an_run_any_g
mov r0, r4
mov r1, r5
bl pulse16_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_37_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #3
mov r3, #0
bl an_run_any_g
mov r0, r4
mov r1, r5
bl pulse16_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_48_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #4
mov r3, #0
bl an_run_any_g
mov r0, r4
mov r1, r5
bl pulse16_func_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse15_func_2:
push {r4, lr}
mov r4, r1
bl sub_8064788_f
ldr r1, =0x8064D65
bx r1
.ltorg

pulse16_func_2:
push {r4, lr}
mov r4, r1
bl sub_8064788_g
ldr r1, =0x8064D65
bx r1
.ltorg

sub_8064788_f:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r0, r5
bl obj_npc_ministep_f
ldr r1, =0x8064795
bx r1
.ltorg

sub_8064788_g:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r0, r5
bl obj_npc_ministep_g
ldr r1, =0x8064795
bx r1
.ltorg

obj_npc_ministep_f:
push {r4, r5, lr}
mov r4, r0
ldr r5, =0x83a71b0
mov r0, #0x36
ldrsh r2, [r4, r0]
lsl r0, r2, #1
add r0, r0, r5
mov r3, #0x38
ldrsh r1, [r4, r3]
mov r3, #0
ldrsh r0, [r0, r3]
cmp r1, r0
bge loc_8068BB4_f
ldr r1, =0x83A719C
lsl r0, r2, #2
add r0, r0, r1
mov r1, #0x38
ldrsh r2, [r4, r1]
ldr r0, [r0]
lsl r2, r2, #2
add r2, r2, r0
ldrh r1, [r4, #0x34]
lsl r1, r1, #0x18
lsr r1, r1, #0x18
ldr r0, =ins_ofs+custom_table
sub r1, #1
lsl r1, r1, #1
ldrsh r1, [r0, r1]
ldr r2, [r2]
mov r0, r4
bl bx_r2
ldr r0, =0x8068B8D
bx r0

loc_8068BB4_f:
mov r0, #0
pop {r4, r5, pc}
.ltorg

obj_npc_ministep_g:
push {r4, r5, lr}
mov r4, r0
ldr r5, =0x83a71b0
mov r0, #0x36
ldrsh r2, [r4, r0]
lsl r0, r2, #1
add r0, r0, r5
mov r3, #0x38
ldrsh r1, [r4, r3]
mov r3, #0
ldrsh r0, [r0, r3]
cmp r1, r0
bge loc_8068BB4_g
ldr r1, =0x83A719C
lsl r0, r2, #2
add r0, r0, r1
mov r1, #0x38
ldrsh r2, [r4, r1]
ldr r0, [r0]
lsl r2, r2, #2
add r2, r2, r0
ldrh r1, [r4, #0x34]
lsl r1, r1, #0x18
lsr r1, r1, #0x18
ldr r0, =ins_ofs+custom_table
add r1, #3
lsl r1, r1, #1
ldrsh r1, [r0, r1]
ldr r2, [r2]
mov r0, r4
bl bx_r2
ldr r0, =0x8068B8D
bx r0

loc_8068BB4_g:
mov r0, #0
pop {r4, r5, pc}
.ltorg

an_run_any_f:
push {r4-r7, lr}
mov r7, r8
push {r7}
sub sp, sp, #0x14
mov r5, r0
mov r8, r1
mov r4, r3
lsl r2, r2, #0x18
lsr r2, r2, #0x18
lsl r4, r4, #0x18
lsr r4, r4, #0x18
mov r1, sp
ldr r0, =0x83a6884
ldmia r0!, {r3, r6, r7}
stmia r1!, {r3, r6, r7}
ldmia r0!, {r3, r6}
stmia r1!, {r3, r6}
mov r0, r5
mov r1, r8
mov r3, r4
bl npc_apply_direction_f
ldr r7, =0x8064729
bx r7
.ltorg

npc_apply_direction_f:
push {r4-r6, lr}
mov r6, r9
mov r5, r8
push {r5, r6}
sub sp, sp, #4
mov r8, r0
mov r9, r1
mov r4, r2
mov r6, r3
lsl r4, r4, #0x18
lsr r4, r4, #0x18
lsl r6, r6, #0x18
lsr r6, r6, #0x18
ldrh r1, [r0, #0x10]
mov r0, sp
strh r1, [r0, #0]
mov r1, r8
ldrh r0, [r1, #0x12]
mov r5, sp
add r5, #2
strh r0, [r5]
mov r0, r8
mov r1, r4
ldr r3, =0x805FBDD
bl bx_r3
ldr r1, =ins_ofs+custom_table
sub r2, r4, #1
lsl r2, r2, #1
ldrsh r0, [r1, r2]
ldr r1, =0x80646AD
bx r1
.ltorg

an_run_any_g:
push {r4-r7, lr}
mov r7, r8
push {r7}
sub sp, sp, #0x14
mov r5, r0
mov r8, r1
mov r4, r3
lsl r2, r2, #0x18
lsr r2, r2, #0x18
lsl r4, r4, #0x18
lsr r4, r4, #0x18
mov r1, sp
ldr r0, =0x83a6884
ldmia r0!, {r3, r6, r7}
stmia r1!, {r3, r6, r7}
ldmia r0!, {r3, r6}
stmia r1!, {r3, r6}
mov r0, r5
mov r1, r8
mov r3, r4
bl npc_apply_direction_g
ldr r7, =0x8064729
bx r7
.ltorg

npc_apply_direction_g:
push {r4-r6, lr}
mov r6, r9
mov r5, r8
push {r5, r6}
sub sp, sp, #4
mov r8, r0
mov r9, r1
mov r4, r2
mov r6, r3
lsl r4, r4, #0x18
lsr r4, r4, #0x18
lsl r6, r6, #0x18
lsr r6, r6, #0x18
ldrh r1, [r0, #0x10]
mov r0, sp
strh r1, [r0, #0]
mov r1, r8
ldrh r0, [r1, #0x12]
mov r5, sp
add r5, #2
strh r0, [r5]
mov r0, r8
mov r1, r4
ldr r3, =0x805FBDD
bl bx_r3
ldr r1, =ins_ofs+custom_table
add r2, r4, #3
lsl r2, r2, #1
ldrsh r0, [r1, r2]
ldr r1, =0x80646AD
bx r1
.ltorg

.align 2
custom_table: .hword 5, 7, 5, 6, 6, 8, 7, 8

jump_1sq_ldmu_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #2
str r0, [sp]
mov r0, r4
mov r2, #1
mov r3, #1
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_1sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

jump_1sq_lumd_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #2
str r0, [sp]
mov r0, r4
mov r2, #2
mov r3, #1
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_1sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

jump_1sq_llmr_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #2
str r0, [sp]
mov r0, r4
mov r2, #3
mov r3, #1
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_1sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

jump_1sq_lrml_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #2
str r0, [sp]
mov r0, r4
mov r2, #4
mov r3, #1
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_1sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

an_jump_1sq_dn_2:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
bl sub_8065028
ldr r1, =0x8066493
bx r1
.ltorg

jump_2sq_ldmu_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #0
str r0, [sp, #0]
mov r0, r4
mov r2, #1
mov r3, #2
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_2sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

jump_2sq_lumd_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #0
str r0, [sp, #0]
mov r0, r4
mov r2, #2
mov r3, #2
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_2sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

jump_2sq_llmr_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #0
str r0, [sp, #0]
mov r0, r4
mov r2, #3
mov r3, #2
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_2sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

jump_2sq_lrml_func:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
mov r0, #0
str r0, [sp, #0]
mov r0, r4
mov r2, #4
mov r3, #2
bl maybe_shadow_1
mov r0, r4
mov r1, r5
bl an_jump_2sq_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
add sp, sp, #4
pop {r4, r5, pc}
.ltorg

maybe_shadow_1:
push {r4, r5, lr}
sub sp, sp, #4
mov r4, r0
mov r5, r1
ldr r0, [sp, #0x10]
lsl r2, r2, #0x18
lsr r2, r2, #0x18
lsl r3, r3, #0x18
lsr r3, r3, #0x18
lsl r0, r0, #0x18
lsr r0, r0, #0x18
str r0, [sp]
mov r0, r4
bl sub_8064E3C
ldr r0, =0x8064f17
bx r0
.ltorg

sub_8064E3C:
push {r4-r7, lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
sub sp, sp, #0x10
mov r7, r0
mov r10, r1
mov r4, r2
mov r8, r3
ldr r0, [sp, #0x30]
lsl r4, r4, #0x18
lsr r4, r4, #0x18
mov r1, r8
lsl r1, r1, #0x18
lsr r1, r1, #0x18
mov r8, r1
lsl r0, r0, #0x18
lsr r0, r0, #0x18
mov r9, r0
ldr r1, =0x83a6958
add r0, sp, #4
mov r2, #6
ldr r3, =0x81E5E79
bl bx_r3
add r5, sp, #0xc
mov r0, #0
strh r0, [r5]
mov r6, r13
add r6, #0xe
strh r0, [r6]
mov r0, r7
mov r1, r4
ldr r3, =0x805FBDD
bl bx_r3
mov r1, r8
lsl r0, r1, #1
add r0, sp
add r0, #4
mov r1, #0
ldrsh r3, [r0, r1]
str r3, [sp, #0]
sub r0, r4, #1
mov r1, #1
eor r0, r1
add r0, #1
ldr r1, =0x8064E93
bx r1
.ltorg

an_jump_2sq_dn_2:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
bl sub_8065028
ldr r1, =0x80650DF
bx r1
.ltorg

sub_8065028:
push {lr}
bl sub_8065000
ldr r1, =0x806502F
bx r1
.ltorg

sub_8065000:
push {lr}
ldr r2, =ins_ofs+sub_8068D3C+1
bl sub_8064F3C
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {pc}
.ltorg

sub_8068D3C:
push {r4-r6, lr}
sub sp, sp, #0xc
mov r4, r0
ldr r1, =0x83a71f8
mov r0, sp
mov r2, #6
ldr r3, =0x81E5E79
bl bx_r3
add r5, sp, #8
ldr r1, =0x83a71fe
mov r0, r5
mov r2, #3
ldr r3, =0x81E5E79
bl bx_r3
mov r6, #0
mov r1, #0x36
ldrsh r0, [r4, r1]
cmp r0, #0
beq loc_8068D6E
ldrh r1, [r4, #0x34]
lsl r1, r1, #0x18
lsr r1, r1, #0x18
sub r1, #1
mov r0, #1
eor r1, r0
add r1, #1
ldr r0, =0x8068D69
bx r0
loc_8068D6E:
ldr r0, =0x8068D6F
bx r0
.ltorg

sub_8064F3C:
push {r4-r7, lr}
mov r7, r8
push {r7}
sub sp, sp, #0x10
mov r6, r0
mov r7, r1
mov r4, r2
ldr r1, =0x83a695e
add r0, sp, #4
mov r2, #6
ldr r3, =0x81E5E79
bl bx_r3
mov r0, r7
bl bx_r4
lsl r0, r0, #0x18
lsr r0, r0, #0x18
mov r8, r0
cmp r0, #1
bne loc_8064FCC
mov r1, #0x36
ldrsh r0, [r7, r1]
lsl r0, r0, #1
add r0, sp
add r0, #4
mov r2, #0
ldrsh r0, [r0, r2]
cmp r0, #0
beq loc_8064FCC
add r4, sp, #0xc
mov r0, #0
strh r0, [r4]
mov r5, r13
add r5, #0xe
strh r0, [r5]
ldrb r0, [r6, #0x18]
lsr r0, r0, #4
sub r0, #1
mov r1, #1
eor r0, r1
add r0, #1
ldr r1, =0x8064F87
bx r1

loc_8064FCC:
ldr r1, =0x8064fcd
bx r1
.ltorg

run_ldmu_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #1
mov r3, #1
bl an_run_any
mov r0, r4
mov r1, r5
bl an_run_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

run_lumd_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #2
mov r3, #1
bl an_run_any
mov r0, r4
mov r1, r5
bl an_run_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

run_llmr_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #3
mov r3, #1
bl an_run_any
mov r0, r4
mov r1, r5
bl an_run_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

run_lrml_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #4
mov r3, #1
bl an_run_any
mov r0, r4
mov r1, r5
bl an_run_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

an_run_dn_2:
push {r4, lr}
mov r4, r1
bl sub_8064788
ldr r1, =0x80652F5
bx r1
.ltorg

pulse_ldmu_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #1
mov r3, #0
bl an_run_any
mov r0, r4
mov r1, r5
bl an_pulse_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_lumd_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #2
mov r3, #0
bl an_run_any
mov r0, r4
mov r1, r5
bl an_pulse_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_llmr_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #3
mov r3, #0
bl an_run_any
mov r0, r4
mov r1, r5
bl an_pulse_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

pulse_lrml_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #4
mov r3, #0
bl an_run_any
mov r0, r4
mov r1, r5
bl an_pulse_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

an_run_any:
push {r4-r7, lr}
mov r7, r8
push {r7}
sub sp, sp, #0x14
mov r5, r0
mov r8, r1
mov r4, r3
lsl r2, r2, #0x18
lsr r2, r2, #0x18
lsl r4, r4, #0x18
lsr r4, r4, #0x18
mov r1, sp
ldr r0, =0x83a6884
ldmia r0!, {r3, r6, r7}
stmia r1!, {r3, r6, r7}
ldmia r0!, {r3, r6}
stmia r1!, {r3, r6}
mov r0, r5
mov r1, r8
mov r3, r4
bl npc_apply_direction
ldr r7, =0x8064729
bx r7
.ltorg

npc_apply_direction:
push {r4-r6, lr}
mov r6, r9
mov r5, r8
push {r5, r6}
sub sp, sp, #4
mov r8, r0
mov r9, r1
mov r4, r2
mov r6, r3
lsl r4, r4, #0x18
lsr r4, r4, #0x18
lsl r6, r6, #0x18
lsr r6, r6, #0x18
ldrh r1, [r0, #0x10]
mov r0, sp
strh r1, [r0, #0]
mov r1, r8
ldrh r0, [r1, #0x12]
mov r5, sp
add r5, #2
strh r0, [r5]
mov r0, r8
mov r1, r4
ldr r3, =0x805FBDD
bl bx_r3
sub r0, r4, #1
mov r1, #1
eor r0, r1
add r0, #1
ldr r1, =0x80646AD
bx r1
.ltorg

an_pulse_dn_2:
push {r4, lr}
mov r4, r1
bl sub_8064788
ldr r1, =0x8064D65
bx r1
.ltorg

sub_8064788:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r0, r5
bl obj_npc_ministep
ldr r1, =0x8064795
bx r1
.ltorg

obj_npc_ministep:
push {r4, r5, lr}
mov r4, r0
ldr r5, =0x83a71b0
mov r0, #0x36
ldrsh r2, [r4, r0]
lsl r0, r2, #1
add r0, r0, r5
mov r3, #0x38
ldrsh r1, [r4, r3]
mov r3, #0
ldrsh r0, [r0, r3]
cmp r1, r0
bge loc_8068BB4
ldr r1, =0x83A719C
lsl r0, r2, #2
add r0, r0, r1
mov r1, #0x38
ldrsh r2, [r4, r1]
ldr r0, [r0]
lsl r2, r2, #2
add r2, r2, r0
ldrh r1, [r4, #0x34]
lsl r1, r1, #0x18
lsr r1, r1, #0x18
sub r1, #1
mov r0, #1
eor r1, r0
add r1, #1
ldr r2, [r2]
mov r0, r4
bl bx_r2
ldr r0, =0x8068B8D
bx r0

loc_8068BB4:
mov r0, #0
pop {r4, r5, pc}
.ltorg

go_ldmu_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #1
bl an_go_any_1
mov r0, r4
mov r1, r5
bl an_go_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

go_lumd_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #2
bl an_go_any_1
mov r0, r4
mov r1, r5
bl an_go_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

go_llmr_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #3
bl an_go_any_1
mov r0, r4
mov r1, r5
bl an_go_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

go_lrml_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #4
bl an_go_any_1
mov r0, r4
mov r1, r5
bl an_go_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

an_go_any_1:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
lsl r2, r2, #0x18
lsr r2, r2, #0x18
bl sub_8064B68
ldr r0, =0x8064be7
bx r0
.ltorg

sub_8064B68:
push {r4-r6, lr}
mov r6, r8
push {r6}
sub sp, sp, #4
mov r6, r0
mov r8, r1
lsl r5, r2, #0x18
lsr r5, r5, #0x18
ldrh r1, [r6, #0x10]
mov r0, sp
strh r1, [r0, #0]
ldrh r0, [r6, #0x12]
mov r4, sp
add r4, #2
strh r0, [r4]
mov r0, r6
mov r1, r5
ldr r3, =0x805FBDD
bl bx_r3
sub r0, r5, #1
mov r1, #1
eor r0, r1
add r0, #1
mov r1, sp
ldr r2, =0x8064b93
bx r2
.ltorg

an_go_dn_2:
push {r4, lr}
mov r4, r1
bl sub_8064C04
ldr r1, =0x8064ca5
bx r1
.ltorg

sub_8064C04:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r0, r5
bl sub_8068C18
ldr r1, =0x8064c11
bx r1
.ltorg

sub_8068C18:
push {r4, lr}
mov r4, r0
ldrh r0, [r4, #0x36]
add r0, #1
strh r0, [r4, #0x36]
lsl r0, r0, #0x10
asr r0, r0, #0x10
cmp r0, #2
bgt loc_8068C3E
ldrh r1, [r4, #0x34]
lsl r1, r1, #0x18
lsr r1, r1, #0x18
sub r1, #1
mov r0, #1
eor r1, r0
add r1, #1
ldr r0, =0x8068c31
bx r0
loc_8068C3E:
ldr r0, =0x8068C3F
bx r0
.ltorg

walk_ldmu_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #1
bl an_walk_any_1
mov r0, r4
mov r1, r5
bl an_walk_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

walk_lumd_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #2
bl an_walk_any_1
mov r0, r4
mov r1, r5
bl an_walk_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

walk_llmr_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #3
bl an_walk_any_1
mov r0, r4
mov r1, r5
bl an_walk_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

walk_lrml_func:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r2, #4
bl an_walk_any_1
mov r0, r4
mov r1, r5
bl an_walk_dn_2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
pop {r4, r5, pc}
.ltorg

an_walk_dn_2:
push {r4, lr}
mov r4, r1
bl an_walk_any_2
lsl r0, r0, #0x18
cmp r0, #0
beq loc_8064aa0
mov r0, #2
strh r0, [r4, #0x32]
mov r0, #1

loc_8064aa0:
pop {r4, pc}
.ltorg

an_walk_any_1:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
lsl r2, r2, #0x18
lsr r2, r2, #0x18
bl sub_80647C0
ldrb r0, [r4, #0x18]
lsl r0, r0, #0x1c
lsr r0, r0, #0x1c
ldr r3, =0x8063441
bl bx_r3
mov r2, r0
lsl r2, r2, #0x18
lsr r2, r2, #0x18
mov r0, r4
mov r1, r5
ldr r3, =0x8063555
bl bx_r3
pop {r4, r5, pc}
.ltorg

sub_80647C0:
push {r4-r6, lr}
mov r6, r8
push {r6}
sub sp, sp, #4
mov r6, r0
mov r8, r1
lsl r5, r2, #0x18
lsr r5, r5, #0x18
ldrh r1, [r6, #0x10]
mov r0, sp
strh r1, [r0, #0]
ldrh r0, [r6, #0x12]
mov r4, sp
add r4, #2
strh r0, [r4]
mov r0, r6
mov r1, r5
ldr r3, =0x805FBDD
bl bx_r3
sub r0, r5, #1
mov r1, #1
eor r0, r1
add r0, #1
mov r1, sp
mov r2, r4
ldr r3, =0x80647ED
bx r3
.ltorg

an_walk_any_2:
push {r4, r5, lr}
mov r4, r0
mov r5, r1
mov r0, r5
bl sub_8068BCC
ldr r1, =0x8064869
bx r1
.ltorg

sub_8068BCC:
push {r4, lr}
mov r4, r0
ldrh r1, [r4, #0x36]
mov r0, #1
and r0, r1
cmp r0, #0
bne loc_8068bec
ldrh r1, [r4, #0x34]
sub r1, #1
mov r0, #1
eor r1, r0
add r1, #1
mov r0, r4
ldr r3, =0x8068be3
bx r3

loc_8068bec:
ldr r0, =0x8068bed
bx r0
.ltorg

bx_r3: bx r3
bx_r2: bx r2
bx_r4: bx r4


How to insert if you don't like the offset 0xF80000 and don't want to use the patch:
1. Repoint the table at 0x3A65BC (3 pointers totally)
2. Change the 0x8F802A8 at the first line to the insert offset of the table + 0x2a8.
3. Compile it and insert it at the insert offset of the table + 0x2a8.
4. Write a script to test.


Credits:
Back~, Invert, Knizz

Hey would you by chance have a variant of that code that skips the evolution cutscene? I'm trying to do it for form changes, and the form change ASM routines here base it off of slot number and don't really give the option to check if you have a certain pokemon or not. For example. One will let you choose any pokemon to evolve into what you want and the other bases it on what slot number the pokemon is in. I need a code that will change a specific pokemon's index number or even making it "evolve" silently.

jiangzhengwenjzw June 6th, 2019 6:03 PM

Quote:

Originally Posted by /JASHIN/ (Post 10029140)
Hey would you by chance have a variant of that code that skips the evolution cutscene? I'm trying to do it for form changes, and the form change ASM routines here base it off of slot number and don't really give the option to check if you have a certain pokemon or not. For example. One will let you choose any pokemon to evolve into what you want and the other bases it on what slot number the pokemon is in. I need a code that will change a specific pokemon's index number or even making it "evolve" silently.

For silent evo you'd better take a look at FBI's routine which is also posted under this thread.

If you still want to use my routine:
Spoiler:
You need to modify the routine because the logic will be completely different and I currently don't have the desire for polishing my old trash routines. In addition, the way to implement it is strongly dependent of the author's requirement.

It will be easy if you want to edit it on your own. Basically it should be:
(From the script's view)
call special XX (the pokemon selection screen with OW callback) -> get the slot number from var -> decrypt its species with a built-in function -> find its evo form in evolution table -> ... ???

Yes, here comes the question: if a pokemon has several different evo method, which should it be taken?
There will be several apparent options:
1. ban those pokemons in this event
2. always take the first form
3. ask the player (how? should we generate a dynamic option list? )
4. randomly pick one (pointless for players abusing S/L)
5. build a custom table to control everything
......

That's why I think you'd better implement it yourself. The code I wrote should be easy to understand but I still want to explain the addresses used here:
Code:

0x300537C: RAM location to store the callback to be called post evolution
0x80568E0: the callback function for returning to OW
0x20370C0: var 0x8004
0x80CDDA8: the evolution function (*)
0x803FBE8: The built-in pokemon data decrypter


*: actually it adds a task but you don't need to know its inner logic if you don't have much experience with ASM hacking.


(I posted detailed explanation because several people asked me about that routine. )

/JASHIN/ June 7th, 2019 6:26 PM

Quote:

Originally Posted by FBI (Post 8513919)
No, no! Use a modified one.
Here:

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r7, lr}
        ldr r0, .SLOT @calculate address of Pokemon we want to evolve
        ldrh r0, [r0]
        mov r1, #0x64
        mul r0, r0, r1
        ldr r1, =(0x2024284)
        add r0, r0, r1
        mov r7, r0
        mov r1, #0xB
        ldr r3, =(0x803FBE8 +1) @get current species, prior to evolving
        bl linker
        mov r5, r0
        bl getEvolvedForm @check what species it evolves into
        mov r6, r0
        mov r0, r7
        mov r1, #0x38
        ldr r3, =(0x803FBE8 +1) @save level before evolution
        bl linker
        mov r4, r0

SetEvolve:
        mov r0, r7 @evolve it
        ldr r2, .VAR
        mov r1, r6
        strh r1, [r2]
        mov r1, #0xB
        ldr r3, =(0x804037C +1)
        bl linker
        mov r0, r7
        ldr r3, =(0x803E47C +1) @recalculate stats
        bl linker

AddToDex:
        mov r0, r6
        ldr r3, =(0x8043298 +1) @get dex index of species
        bl linker
        mov r0, r6
        mov r1, #0x2
        ldr r3, =(0x8088E74 +1) @normal dex
        bl linker
        mov r0, r6
        mov r1, #0x3
        ldr r3, =(0x8088E74 +1) @national
        bl linker

FinishCalc:
        mov r0, r7 @check current level (after evolving)
        mov r1, #0x38
        ldr r3, =(0x803FBE8 +1)
        bl linker
        cmp r0, r4 @exp curves skewed level
        bne AdjustLvl
        b Nickname

getEvolvedForm:
        ldr r0, =(0x20370BC)
        ldrh r0, [r0]
        bx lr

Nickname:
        mov r0, r7
        ldr r1, =(0x2021CD0) @store current nickname here
        mov r2, r1
        mov r1, #0x2
        ldr r3, =(0x803FBE8 +1)
        bl linker
        ldr r0, =(0x8245EE0)@calculate species default name
        mov r1, #0xB
        mul r1, r1, r5
        add r1, r1, r0
        mov r5, r1
        ldr r1, =(0x2021CD0)
        mov r4, r1
        mov r0, #0x0

checkEqual:
        cmp r0, #0xA            @While nickname has char
        beq setName
        add r5, r5, #0x1        @get next char of species name
        ldrb r1, [r5]
        add r4, r4, #0x1        @get next char of nickname
        ldrb r2, [r4]
        cmp r2, r1                @if x != y ==> has nickname
        bne end
        cmp r2, #0xFF          @strings are 0xFF terminated
        beq checkOne
        b contLoop

checkOne:
        cmp r1, #0xFF
        beq setName
        b end

contLoop:
        add r0, r0, #0x1 @loop counter ++
        b checkEqual

setName:
        ldr r2, =(0x8245EE0) @set nickname as species name
        mov r0, #0xB
        mul r6, r6, r0
        add r6, r6, r2
        mov r0, r7
        mov r2, r6
        mov r1, #0x2
        ldr r3, =(0x804037C +1)
        bl linker
        b end

AdjustLvl:
        cmp r0, r4
        beq Nickname
        mov r2, r0
        mov r0, r7
        mov r1, #0x19
        ldr r3, =(0x803FBE8 +1) @x = currentExp * 1.1
        bl linker
        mov r1, r0
        lsr r0, #0x4
        cmp r2, r4          @if current lvl < old lvl; currentExp -= x
        bls subtract
        add r1, r1, r0
        b updateExp

subtract:
        sub r1, r1, r0      @else currentExp += x

updateExp:
        ldr r2, .VAR
        str r1, [r2]
        mov r1, #0x19
        mov r0, r7
        ldr r3, =(0x804037C +1)
        bl linker
        mov r0, r7
        ldr r3, =(0x803E47C +1)
        bl linker
        mov r0, r7
        mov r1, #0x38
        ldr r3, =(0x803FBE8 +1)
        bl linker
        b AdjustLvl

end:
        pop {r0-r7, pc}

linker:
        bx r3

.align 2

.VAR:
        .word 0x20270B8 + (0x8000 *2) @change to any 2 byte free space in RAM
.SLOT:
        .word 0x20270B8 + (0x8001 *2) @slot of Pokemon to evolve




That one uses the variable 0x8002 to determine it's evolution. You can use it to evolve into a specific evolution that way. Or be silly and evolve Rattata into a Venasaur :3


Mini update:

Remember how the TMs were showing quantities? Well I fixed that now. I'll edit my original post with the details as well. Here it is:

Compile and insert into free space:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        cmp r5, #0x0
        bne end
        ldr r3, =(0x8131EFE +1)
        bx r3

end:
        mov r0, r7
        mov r1, #0x8
        mov r2, r4
        ldr r6, =(0x81335B0 +1)
        bl link
        ldr r3, =(0x8131EFE +1)
        bx r3

link:
        bx r6

.align 2




Now navigate to 0x131EF4 and insert:
Code:

00 48 00 47 XX XX XX 08


Where XX XX XX is the pointer to where you assembled the routine +1

Now navigate to 0x131EA5 and change the byte to E0
That's all.
http://i.imgur.com/3nina1p.png?1

So I'm having an issue using both codes when using them. The first code only works on pokemon that are not part of my expanded dex, as well as it doesn't work on custom evolutions for some reason. For example, I use it on deoxys to try to evolve it to some random pokemon and it just freezes the game upon execution.

The second code works for my expanded mons, but for some reason, when I use it on expanded pokemon it changes the pokemon's name. For example I evolved clefairy into Ribombee and its name turned into SHADOW PU lol what is going on here?

dGxx July 6th, 2019 4:00 PM

Hi, I'm new here, don't know if this has been said already, but I've been working on my own hack for a while, I've been stuck at this one thing, i made the evolution stones like water stone, etc, cost like 20,000 pokedollars, but when i go to buy them, i see they cost ?000...when i select it, it shows it's 20,000, i just would like to increase the length of the prices to show 5 digits, i followed the advice of a person named Touched, he said to change 04 to 05 at some offset i cant remeber right now...i changed it to 05 but the game froze, changed it back to 04 and the game went back to normal. Please help me, anyone, I'm doing fire red

RichterSnipes July 7th, 2019 6:11 PM

Quote:

Originally Posted by dGxx (Post 10041482)
Hi, I'm new here, don't know if this has been said already, but I've been working on my own hack for a while, I've been stuck at this one thing, i made the evolution stones like water stone, etc, cost like 20,000 pokedollars, but when i go to buy them, i see they cost ?000...when i select it, it shows it's 20,000, i just would like to increase the length of the prices to show 5 digits, i followed the advice of a person named Touched, he said to change 04 to 05 at some offset i cant remeber right now...i changed it to 05 but the game froze, changed it back to 04 and the game went back to normal. Please help me, anyone, I'm doing fire red

This isn't really the place to ask these questions. This thread is about developing ASM routines to add/modify functions to the game. The Quick Research & Development Thread is what you're looking for.

Your answer seems to be there, too! Try following this post and see if it fixes your problems.

dGxx July 7th, 2019 10:42 PM

Thanks Ritcher! I thought I could ask here because I thought I needed an ASM code or something, but now I see I just needed to change 3 different value not just two. Thanks I did get the result I needed. And thanks to all you guys being so great at all this ASM coding and being so helpful with your great skill of programming!

RichterSnipes July 10th, 2019 3:35 PM

Quote:

Originally Posted by dGxx (Post 10041901)
Thanks Ritcher! I thought I could ask here because I thought I needed an ASM code or something, but now I see I just needed to change 3 different value not just two. Thanks I did get the result I needed. And thanks to all you guys being so great at all this ASM coding and being so helpful with your great skill of programming!

No problem, glad to be of help!

Anyways, I've got my own idea. I don't know how much anyone cares to implement something like this, or if it's even possible. It's a pretty crazy thing to begin with. I'll still ask nonetheless.

Would it be possible to modify the GBA games to have two dedicated save files for two different people? The games already use all the space for a second save file to store a backup save. If possible, why not make a more practical use for it?

I know that this would cause problems with functions that don't require you to load up a save first, such as New Game, Options, Mystery Gift, GameCube to Game Boy Advance linking, migrating Pokémon to the Gen IV games, and save editing. My idea would be to make it so the most recently used save is the "active" save file. This way these functions interface with the active save, the Options menu reflects the settings of the active user, and New Game will save over the active save. Or, alternatively, change the New Game saving situation to be like the later games where you have to delete a save first. Then you can change the active save by loading up the "secondary" save file, which would now push the other save into secondary status.

I've always loved the idea of having multiple save files on one Pokémon cartridge. I know that it'll never be a feature in the official games, early on because of technical reasons (the first couple of generations couldn't handle it) and later on strictly for monetary reasons (buy more copies of the games!). But it'd still be a watershed moment in my eyes for it to become a reality.

dGxx July 12th, 2019 8:02 PM

Quote:

Originally Posted by RichterSnipes (Post 10042722)
No problem, glad to be of help!

Anyways, I've got my own idea. I don't know how much anyone cares to implement something like this, or if it's even possible. It's a pretty crazy thing to begin with. I'll still ask nonetheless.

Would it be possible to modify the GBA games to have two dedicated save files for two different people? The games already use all the space for a second save file to store a backup save. If possible, why not make a more practical use for it?

I know that this would cause problems with functions that don't require you to load up a save first, such as New Game, Options, Mystery Gift, GameCube to Game Boy Advance linking, migrating Pokémon to the Gen IV games, and save editing. My idea would be to make it so the most recently used save is the "active" save file. This way these functions interface with the active save, the Options menu reflects the settings of the active user, and New Game will save over the active save. Or, alternatively, change the New Game saving situation to be like the later games where you have to delete a save first. Then you can change the active save by loading up the "secondary" save file, which would now push the other save into secondary status.

I've always loved the idea of having multiple save files on one Pokémon cartridge. I know that it'll never be a feature in the official games, early on because of technical reasons (the first couple of generations couldn't handle it) and later on strictly for monetary reasons (buy more copies of the games!). But it'd still be a watershed moment in my eyes for it to become a reality.

yes richter, I agree with you and your idea as well. My daughter is always playing my savefiles, luckily for the switch has different profiles so she plays her own pokemon go pikachu file while she doesnt mess with mine. It's a great feature!

Sudonim July 17th, 2019 5:11 PM

I'm going to go ahead and feel free to request something. So a while back i wanted to edit emerald to force only super effective moves to deal damage, and i figured the best way to do this was to edit the type chart. After doing that and playing the game, i quickly realized that editing the type chart also applies to status moves (e.g. Toxic, Growl, etc.) which is undesirable. I could have also edited the abilities for every Pokémon to have Wonder guard instead, but i feel like that's taking a lazy approach, and in that situation Slaking not having truant would make it even more over powered. So now that i have free time again i decided to come back to this project, and see if i can finally make this come to fruition. I would do this myself, but i don't understand ASM at all, and through my searching i haven't come up with any info about how i would even go about adding this rule in (I'm guessing it needs to be added to the damage calculation?).

TL;DR Wonder Guard at all times while keeping abilities and status moves in tact.

seoluis August 25th, 2019 10:14 PM

i have same issues in pokemon stadium i cant add new types due to next addresses being for moves animations , accuracy and evasion i dont know how to reallocate the chart

Xcisor August 26th, 2019 3:33 AM

Can someone please help me with the Sitrus Berry Updates for Pokemon Emerald? I'm a bit new to ASM and not sure if I should run an overworld script with callasm command in game somewhere to change the effect the Sitrus Berry has or if I insert the pointer somewhere else in the Rom to get the desired effect out of the ASM in the First Post.

Diluting the process down to Hex and Free Space finding would be appreciated too!

Right now I've got an ASM folder with the thumb compiler. What all would I then need to copy/paste save and convert to HEX? With such a HEX code I'd insert it into freespace ending in 0 and then where do I go from here?

Zeturic August 26th, 2019 12:09 PM

After spending way too much time tinkering with the build system and README, I can finally present:

Move Item [FR]

Black and White 2 introduced a feature where you can move items directly between two Pokémon in your party from within the party menu, rather than having to use the bag as middle man. This ports that feature to FR ROMs.

https://github.com/Zeturic/bpre-move-item/blob/master/bpre-move-item.gif?raw=true

K1llerCruz September 18th, 2019 12:04 PM

I would like to ask if anyone can do a routine wich maximizes the IV's/EV's stats of my team's first pokemon

U.Flame September 25th, 2019 3:48 AM

Having some issues with Spherical Ice's Dive ASM here in this thread: https://www.pokecommunity.com/showthread.php?t=257723

This is the ASM as I inserted it:
Spoiler:
.thumb
.global firered_dive

@ FireRed v1.0 HM08 DIVE Port
@ Credits: Spherical Ice, Squeetz

@ CHANGE THESE:
.equ offset, 0xB7DCB0 @ ROM address of 0x400 bytes of free space
.equ OW_MALE_DIVE, 148 @ male player's diving overworld sprite number
.equ OW_FEMALE_DIVE, 149 @ female player's diving overworld sprite number
.equ FLAG_ALLOW_DIVE, 0x827 @ flag which allows the use of Dive
@ YOU MUST CHANGE THE ABOVE VALUES

@ INSTALL:
@ 1. Change the .equ values above, labelled CHANGE THESE
@ 2. If you wish to disable badge checking, follow the DISABLE BADGE CHECKING instructions below
@ 3. Save this file
@ 4. Assemble this file using the following command:
@ thumb firered_dive.s firered_dive.gba
@ 5. Create a .IPS patch using Lunar IPS:
@ Use the included base.gba file as the base ROM
@ Use the newly generated firered_dive.gba file as the modified ROM
@ 6. Patch your FireRed v1.0 ROM with the generated .IPS patch
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ DISABLE BADGE CHECKS:
@ Find and remove the appropriately labelled lines of code below
@ Ctrl + F: REMOVE THE FOLLOWING 5 LINES TO DISABLE BADGE CHECK
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ MAKE DIVE POSSIBLE IN MAPS:
@ Set the second behaviour byte of Dive-able tiles to the value of DIVE_TILE_BYTE below (0x23 by default)
@ Set their second behaviour byte of Emerge-able tiles to the value of EMERGE_TILE_BYTE below (0x24 by default)
@ Set underwater maps' light level (the Type: field in the Header view on AdvanceMap) to Underwater (0x5)
@ Create Emerge map connections to underwater maps leading to their surface maps
@ Create Dive map connections to surface maps leading to their underwater maps
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ Changing these is optional (they are the default FireRed currently)
.equ OW_MALE_WALK, 0 @ male player's normal, walking overworld sprite number
.equ OW_MALE_CYCLE, 1 @ male player's cycling overworld sprite number
.equ OW_MALE_SURF, 2 @ male player's surfing/"sat down" overworld sprite number
.equ OW_MALE_ITEM_0, 3 @ male player's first item usage overworld sprite number
.equ OW_MALE_FISH, 4 @ male player's fishing overworld sprite number
.equ OW_MALE_ITEM_1, 5 @ male player's second item usage overworld sprite number
.equ OW_FEMALE_WALK, 7 @ female player's normal, walking overworld sprite number
.equ OW_FEMALE_CYCLE, 8 @ female player's cycling overworld sprite number
.equ OW_FEMALE_SURF, 9 @ female player's surfing/"sat down" overworld sprite number
.equ OW_FEMALE_ITEM_0, 10 @ female player's first item usage overworld sprite number
.equ OW_FEMALE_FISH, 11 @ female player's fishing overworld sprite number
.equ OW_FEMALE_ITEM_1, 12 @ female player's second item usage overworld sprite number
.equ DIVE_TILE_BYTE, 0x23 @ second behaviour byte value for diving
.equ EMERGE_TILE_BYTE, 0x24 @ second behaviour byte value for emerging
.equ FLAG_ALLOW_RUN, 0x82F @ flag which allows the use of the Running Shoes
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ DO NOT CHANGE THESE VALUES:
.equ rom, 0x08000000
@ DO NOT CHANGE THE ABOVE VALUES

@ Hooks and branches
.org 0x5BA30, 0xFF
ldr r0, =(disable_running_underwater + rom + 1)
bx r0
.pool

.org 0x5C7F4, 0xFF
.word player_overworld_list + rom

.org 0x5C826, 0xFF
ldr r1, =(get_gender_from_sprite + rom + 1)
bx r1
.pool

.org 0x5C9B0, 0xFF
.word walkrun_overworld_list + rom

.org 0x5C9BA, 0xFF
cmp r2, #3

.org 0x5C9F4, 0xFF
.word walkrun_overworld_list + rom

.org 0x6CB30, 0xFF
ldr r0, =(check_for_events + rom + 1)
bx r0
.pool

.org 0x6CCCC, 0xFF
ldr r1, =(check_dive + rom + 1)
bx r1
.pool

.org 0x6DF78, 0xFF
b 0x6DF84

.org 0x35B854, 0xFF
.word change_sprite_to_diving + rom + 1

.org 0x471EEC, 0xFF
.word player_behaviour_dive + rom + 1

.org offset, 0xFF
@ New data
player_overworld_list:
.byte OW_MALE_WALK, OW_FEMALE_WALK
.byte OW_MALE_CYCLE, OW_FEMALE_CYCLE
.byte OW_MALE_SURF, OW_FEMALE_SURF
.byte OW_MALE_ITEM_0, OW_FEMALE_ITEM_0
.byte OW_MALE_FISH, OW_FEMALE_FISH
.byte OW_MALE_ITEM_1, OW_FEMALE_ITEM_1
.byte OW_MALE_DIVE, OW_FEMALE_DIVE

walkrun_overworld_list:
.byte OW_MALE_WALK, 0b00001
.byte OW_MALE_CYCLE, 0b00010
.byte OW_MALE_SURF, 0b01000
.byte OW_MALE_DIVE, 0b10000
.byte OW_FEMALE_WALK, 0b00001
.byte OW_FEMALE_CYCLE, 0b00010
.byte OW_FEMALE_SURF, 0b01000
.byte OW_FEMALE_DIVE, 0b10000

@ New code
disable_running_underwater:
ldr r6, =(0x02037078) @ walkrun_state
ldrb r1, [r6, #0] @ walkrun->bitfield
mov r0, #16
and r0, r1
cmp r0, #0
bne i_forgot_what_this_label_is
mov r0, #2
and r5, r0
cmp r5, #0
beq cannot_run
ldr r0, =(FLAG_ALLOW_RUN)
ldr r3, =(0x0806E6D0+1) @ flag_check
bl call_via_r3
lsl r0, r0, #24
lsr r0, r0, #24
cmp r0, #0
beq cannot_run
ldr r2, =(0x02036E38) @ npc_states
ldrb r1, [r6, #5]
lsl r0, r1, #3
add r0, r0, r1
lsl r0, r0, #2
add r0, r0, r2
ldrb r0, [r0, #30]
ldr r3, =(0x080BD488+1) @ is_tile_to_run_on
bl call_via_r3
cmp r0, #0
bne cannot_run

can_run:
ldr r0, =(0x0805BA5A+1)
bx r0

i_forgot_what_this_label_is:
ldr r0, =(0x0805BA9E+1)
bx r0

cannot_run:
ldr r0, =(0x0805BA8C+1)
bx r0

.pool

get_gender_from_sprite:
lsl r0, r0, #24
lsr r0, r0, #24
cmp r0, #OW_MALE_DIVE
beq male
cmp r0, #OW_FEMALE_DIVE
beq female
cmp r0, #OW_FEMALE_FISH
bgt male
cmp r0, #OW_FEMALE_WALK
blt male

female:
mov r0, #1
b return_to_x5C838

male:
mov r0, #0

return_to_x5C838:
ldr r1, =(0x0805C838 + 1)
bx r1
.pool

check_for_events:
mov r0, #0x80
and r0, r1
cmp r0, #0
beq check_aftermove
bl consider_dive_emerging
cmp r0, #1
beq something_happened

check_aftermove:
ldrb r1, [r5]
mov r0, #0x40
and r0, r1
cmp r0, #0
beq check_move
ldr r0, =(0x0806CB38 + 1)
bx r0

something_happened:
ldr r0, =(0x0806CB6C + 1)
bx r0

check_move:
ldr r0, =(0x0806CB74 + 1)
bx r0
.pool

consider_dive_emerging:
push {lr}
@ REMOVE THE FOLLOWING 5 LINES TO DISABLE BADGE CHECK
ldr r0, =(FLAG_ALLOW_DIVE)
ldr r1, =(0x0806E6D0 + 1) @ checkflag
bl call_via_r1
cmp r0, #0
beq no_emerging
@ REMOVE THE ABOVE 5 LINES TO DISABLE BADGE CHECK
ldr r0, =(0x02036DFC) @ map_header
ldrb r0, [r0, #23] @ map_header->light_level
cmp r0, #5
bne no_emerging
bl get_block_secondary_role
cmp r0, #EMERGE_TILE_BYTE
bne no_emerging
ldr r0, =(0x081BE3D4) @ emerge_script
ldr r1, =(0x08069AE4 + 1) @ script_start
bl call_via_r1
mov r0, #1
b dive_return

no_emerging:
mov r0, #0

dive_return:
pop {r1}
bx r1
.pool

check_dive:
ldrb r1, [r5]
mov r0, #1
and r0, r1
cmp r0, #0
beq no_dive
bl consider_diving
cmp r0, #1
beq something_happened

no_dive:
ldrb r1, [r5]
mov r0, #4
and r0, r1
cmp r0, #0
beq something
ldr r2, =(0x0806CCD6 + 1)
bx r2

something:
ldr r0, =(0x0806CCFC + 1)
bx r0
.pool

consider_diving:
push {lr}
@ REMOVE THE FOLLOWING 5 LINES TO DISABLE BADGE CHECK
ldr r0, =(FLAG_ALLOW_DIVE)
ldr r1, =(0x0806E6D0 + 1) @ checkflag
bl call_via_r1
cmp r0, #0
beq cant_dive
@ REMOVE THE ABOVE 5 LINES TO DISABLE BADGE CHECK
bl get_block_secondary_role
cmp r0, #DIVE_TILE_BYTE
bne cant_dive
ldr r0, =(0x081BE38B) @ dive_script
ldr r1, =(0x08069AE4 + 1) @ script_start
bl call_via_r1
mov r0, #1
b dive_pop

cant_dive:
mov r0, #0

dive_pop:
pop {r1}
bx r1
.pool

get_block_secondary_role:
push {r4, lr}
sub sp, sp, #4
mov r4, sp
add r4, #2
mov r0, sp
mov r1, r4
ldr r3, =(0x0805C538 + 1) @ player_get_pos_to
bl call_via_r3
mov r0, sp
mov r1, #0
ldsh r0, [r0, r1]
mov r2, #0
ldsh r1, [r4, r2]
lsl r0, r0, #16
asr r0, r0, #16
lsl r1, r1, #16
asr r1, r1, #16
mov r2, #8
ldr r3, =(0x08058F48 + 1) @ cur_mapdata_block_get_field_at
bl call_via_r3
lsl r0, r0, #16
lsr r0, r0, #24
add sp, sp, #4
pop {r4}
pop {r1}
bx r1
.pool

player_behaviour_dive:
push {r4, lr}
ldr r0, =(0x02037078) @ walkrun_state
ldrb r0, [r0, #5] @ walkrun_state->npcid
lsl r4, r0, #3
add r4, r4, r0
lsl r4, r4, #2
ldr r0, =(0x02036E38) @ npc_states
add r4, r4, r0
mov r0, #6
ldr r3, =(0x0805C808 + 1) @ get_sprite_for_player
bl call_via_r3
add r1, r0, #0
lsl r1, r1, #24
lsr r1, r1, #24
add r0, r4, #0
ldr r3, =(0x081507BC + 1) @ npc_change_sprite_call
bl call_via_r3
ldrb r1, [r4, #24]
lsr r1, r1, #4
add r0, r4, #0
ldr r3, =(0x0805F218 + 1) @ npc_turn
bl call_via_r3
mov r0, #16
ldr r3, =(0x0805C970 + 1) @ change_sprite_bitfield
bl call_via_r3
ldrb r0, [r4, #4]
ldr r3, =(0x080DC6B0 + 1) @ bobbing
bl call_via_r3
strb r0,[r4, #26]
pop {r4}
pop {r0}
bx r0
.pool

change_sprite_to_diving:
push {lr}
mov r0, #4

set:
ldr r1, =(0x08150498 + 1) @ set_player_behaviour
bl call_via_r1
pop {r1}

call_via_r1:
bx r1

call_via_r3:
bx r3
.pool

.org 0xFFFFFF, 0xFF
.byte 0xFF


I had asked about this in Rom Hacking Help with no luck, since this is an ASM specific thread maybe this is a better place to ask. Basically, it functions but has problems with female players. Firstly, the Dive sprite uses the Dive overworld sprites but with the palette of the normal walking overworld sprites. It does this for both genders, but upon entering and exiting a menu or battle, the palette is corrected to the dive sprite palette. This in itself can be a non-issue if both sprites share palettes. For male players, this is the only issue.

The main problem is with female players upon entering a menu/battle, the dive sprite is reverted to the normal walking sprite. This includes behavior as well, no longer bobbing and is now able to run. There's an additional oddity if the dive and walk sprites are different sizes. The reverted sprite appears glitched, but upon another menu/battle, fully reverts to a normal looking walk state.

So what's causing female players to undo the dive state like that, and not males? One other thing I noticed is that the underwater fog still appears but the bubbles only appear after entering and exiting a menu. I tried implementing this in both my ongoing project and in vanilla Firered, no change in results. Then I checked diving in Pokemon Gaia, and found that the sprites function perfectly well for both genders, no palette issue, no reversion issue. But that the bubbles not appearing until after a menu thing is there. My main concern is just the female players breaking. The palette and bubbles issue isn't important, I can live with that, but I can't have players walking underwater.

jvhbv October 16th, 2019 10:50 AM

Quote:

Originally Posted by FBI (Post 8540240)

Getting IVs and EVs



The routines are very similar so I ended up just combining the two routines into one. Basically given a slot number of a Pokemon in 0x8004, the routines will return the EVs or IVs, respectively, into the vars 0x8005-0x800A with 0x8003 as the IV/EV switch.


How to insert:

Compile and insert the following routine into free space:

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r5, lr}
        mov r4, #0x0

loop:
        cmp r4, #0x6
        bhi end
        ldr r0, =(0x20370C0) @var 0x8004 = slot number
        ldrh r0, [r0]
        mov r1, #0x64
        mul r1, r1, r0
        ldr r0, =(0x2024284)
        add r0, r0, r1
        ldr r3, =(0x20370BE)
        ldrh r3, [r3]
        cmp r3, #0x0
        beq EVs
        add r1, r1, #0x27 @IV
        b continue

EVs:
        add r1, r1, #0x1A

continue:
        ldr r2, =(0x803FBE8 +1)
        bl linker
        mov r1, r0
        @get var
        ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
        lsl r0, r4, #0x1
        add r2, r2, r0
        strh r1, [r2] @store IV in var
        add r4, r4, #0x1
        b loop

linker:
        bx r2

end:
        pop {r0-r5, pc}

.align 2





Usage:
setvar 0x8003 0x[anything except 0 = IV, 0 = EV]
setvar 0x8004 0x[slot number 0 to 5]
callasm 0x[this routine +1]

The variables will be:
0x8005: HP IV/EV
0x8006: Atk IV/EV
0x8007: Def IV/EV
0x8008: Spd IV/EV
0x8009: S.atk IV/EV
0x800A: S.def IV/EV

So for about the last 10 hours I've been trying to figure something out with this code.
It works completely fine, other than the fact that when I run it, it sets all 6 variables to the IV of the pokemon I specified in the scripts HP IV

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r5, lr} @loads registers r0-r5
        mov r4, #0x0 @copies 0(aka 0x0) to register r4

loop:
        cmp r4, #0x6 @finds the difference between the value in register r4 and the number 6(aka 0x6)
        bhi end @I believe this is roughly equivalent to if(r4==6) goto end
        ldr r0, =(0x20370C0) @var 0x8004 = slot number
        ldrh r0, [r0] @loads register r0 at the offset stored in r0 (set right before this to 0x20370C0) ONLY A HALFWORD IS LOADED
        mov r1, #0x64 @copies 100(aka 0x64) to register r1
        mul r1, r1, r0 @multiplies r0(the value at 0x20370C0/var 0x8004) by r1(100 aka 0x64) and stores the result in r1
        ldr r0, =(0x2024284) @loads register r0 at offset 0x2024284, upon inspection of this memory location, it is where the pokemon in your party are stored
        add r0, r0, r1 @adds the value in r1 to the offset r0 is loaded at, getting the party member location
        ldr r3, =(0x20370BE) @loads register r3 at 0x20370BE, the location of var 0x8003
        ldrh r3, [r3] @reads the halfword at 0x20370BE and writes it to r3, aka sets r3 equal to var 8003
        cmp r3, #0x0 @checks if r3(at this point effectively var 0x8003) is 0
        beq EVs @goes to evs if var 0x8003 is 0
        add r1, r1, #0x27 @IV r1 at this point is equal to the offset at whatever pokemon party number you want, adding 0x27 sets the offset to the ivs section of the pokemon's data
        b continue @goes to continue

EVs:
        add r1, r1, #0x1A

continue:
        ldr r2, =(0x803FBE8 +1) @I think this sets register r2 equal to the offset 0x803FBE9
        bl linker @branches to linker and stores the current offset in the link register(r14)
        mov r1, r0 @copies r0 to r1
        @get var
        ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
        lsl r0, r4, #0x1 @I think shifts r0 to the left(subtracts 1 from r0)
        add r2, r2, r0
        strh r1, [r2] @store IV in var
        add r4, r4, #0x1 @adds 1 to the value of r4, allowing the assembly to terminate once it runs 6 times
        b loop @goes to loop

linker:
        bx r2 @branches to the offset stored in r2

end:
        pop {r0-r5, pc}

.align 2




I've taken the code and put in comments on each line summarizing what I understand each line to do. Am I mistaken? Am I completely wrong?

Spoiler:

Code:

//---------------
#org 0x2514D0
lock
faceplayer
msgbox 0x82515D0 MSG_YESNO //"Would you like to know the\npotent..."
compare LASTRESULT 0x0
if 0x1 goto 0x8251570
setvar 0x8003 0x1
setvar 0x8004 0x0
callasm 0x8251C51
buffernumber 0x0 0x8005
buffernumber 0x1 0x8006
msgbox 0x8251610 MSG_NORMAL //"HP: [buffer1] IVs\nAttack: [buffer..."
buffernumber 0x0 0x8007
buffernumber 0x1 0x8008
msgbox 0x8251630 MSG_NORMAL //"Defence: [buffer1] IVs\nSpeed: [bu..."
buffernumber 0x0 0x8009
buffernumber 0x1 0x800A
msgbox 0x8251650 MSG_NORMAL //"Special Attack: [buffer1] IVs\nSpe..."
end

//---------------
#org 0x251570

//---------
// Strings
//---------
#org 0x2515D0
= Would you like to know the\npotential of your Pokémon?

#org 0x251610
= HP: [buffer1] IVs\nAttack: [buffer2] IVs

#org 0x251630
= Defence: [buffer1] IVs\nSpeed: [buffer2] IVs

#org 0x251650
= Special Attack: [buffer1] IVs\nSpecial Defence: [buffer2] IVs.




with the compiled thing ending up as

Code:

0x08251C50        3F B5 00 24 05 2C 17 D8 0C 48 00 88 64 21 41 43
0x08251C60        0B 48 40 18 0B 4B 1B 88 00 2B 01 D0 27 31 00 E0
0x08251C70        1A 31 09 4A 00 F0 07 F8 01 1C 08 4A 60 00 12 18
0x08251C80        11 80 01 34 E6 E7 10 47 3F BD C0 46 C0 70 03 02
0x08251C90        86 42 02 02 BE 70 03 02 E9 FB 03 08 C4 70 03 02


Everything I have there follows the implementation instructions to a T, yet the memory still shows

Code:

0x020370BD        00 01 00 00 00 19 00 19 00 19 00 19 00 19 00 19
0x020370CD        00 19 00 01 00 02 00 04 00 00 00 00 00 FF 00 01


and just to make sure it wasn't a statistical fluke, I ran the same script with 5 or so more randomly encountered pokemon and ran them through an IV calculator. Each time, the HP IV shown by the ASM was correct, but then copied it to every other variable set in the script.

jvhbv October 16th, 2019 11:00 AM

Quote:

Originally Posted by FBI (Post 8540240)

Getting IVs and EVs



The routines are very similar so I ended up just combining the two routines into one. Basically given a slot number of a Pokemon in 0x8004, the routines will return the EVs or IVs, respectively, into the vars 0x8005-0x800A with 0x8003 as the IV/EV switch.


How to insert:

Compile and insert the following routine into free space:

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r5, lr}
        mov r4, #0x0

loop:
        cmp r4, #0x6
        bhi end
        ldr r0, =(0x20370C0) @var 0x8004 = slot number
        ldrh r0, [r0]
        mov r1, #0x64
        mul r1, r1, r0
        ldr r0, =(0x2024284)
        add r0, r0, r1
        ldr r3, =(0x20370BE)
        ldrh r3, [r3]
        cmp r3, #0x0
        beq EVs
        add r1, r1, #0x27 @IV
        b continue

EVs:
        add r1, r1, #0x1A

continue:
        ldr r2, =(0x803FBE8 +1)
        bl linker
        mov r1, r0
        @get var
        ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
        lsl r0, r4, #0x1
        add r2, r2, r0
        strh r1, [r2] @store IV in var
        add r4, r4, #0x1
        b loop

linker:
        bx r2

end:
        pop {r0-r5, pc}

.align 2





Usage:
setvar 0x8003 0x[anything except 0 = IV, 0 = EV]
setvar 0x8004 0x[slot number 0 to 5]
callasm 0x[this routine +1]

The variables will be:
0x8005: HP IV/EV
0x8006: Atk IV/EV
0x8007: Def IV/EV
0x8008: Spd IV/EV
0x8009: S.atk IV/EV
0x800A: S.def IV/EV

So for about the last 10 hours I've been trying to figure something out with this code.
It works completely fine, other than the fact that when I run it, it sets all 6 variables to the IV of the pokemon I specified in the scripts HP IV

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r5, lr} @loads registers r0-r5
        mov r4, #0x0 @copies 0(aka 0x0) to register r4

loop:
        cmp r4, #0x6 @finds the difference between the value in register r4 and the number 6(aka 0x6)
        bhi end @I believe this is roughly equivalent to if(r4==6) goto end
        ldr r0, =(0x20370C0) @var 0x8004 = slot number
        ldrh r0, [r0] @loads register r0 at the offset stored in r0 (set right before this to 0x20370C0) ONLY A HALFWORD IS LOADED
        mov r1, #0x64 @copies 100(aka 0x64) to register r1
        mul r1, r1, r0 @multiplies r0(the value at 0x20370C0/var 0x8004) by r1(100 aka 0x64) and stores the result in r1
        ldr r0, =(0x2024284) @loads register r0 at offset 0x2024284, upon inspection of this memory location, it is where the pokemon in your party are stored
        add r0, r0, r1 @adds the value in r1 to the offset r0 is loaded at, getting the party member location
        ldr r3, =(0x20370BE) @loads register r3 at 0x20370BE, the location of var 0x8003
        ldrh r3, [r3] @reads the halfword at 0x20370BE and writes it to r3, aka sets r3 equal to var 8003
        cmp r3, #0x0 @checks if r3(at this point effectively var 0x8003) is 0
        beq EVs @goes to evs if var 0x8003 is 0
        add r1, r1, #0x27 @IV r1 at this point is equal to the offset at whatever pokemon party number you want, adding 0x27 sets the offset to the ivs section of the pokemon's data
        b continue @goes to continue

EVs:
        add r1, r1, #0x1A

continue:
        ldr r2, =(0x803FBE8 +1) @I think this sets register r2 equal to the offset 0x803FBE9
        bl linker @branches to linker and stores the current offset in the link register(r14)
        mov r1, r0 @copies r0 to r1
        @get var
        ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
        lsl r0, r4, #0x1 @I think shifts r0 to the left(subtracts 1 from r0)
        add r2, r2, r0
        strh r1, [r2] @store IV in var
        add r4, r4, #0x1 @adds 1 to the value of r4, allowing the assembly to terminate once it runs 6 times
        b loop @goes to loop

linker:
        bx r2 @branches to the offset stored in r2

end:
        pop {r0-r5, pc}

.align 2




with the compiled thing ending up as

Code:

0x08251C50        3F B5 00 24 05 2C 17 D8 0C 48 00 88 64 21 41 43
0x08251C60        0B 48 40 18 0B 4B 1B 88 00 2B 01 D0 27 31 00 E0
0x08251C70        1A 31 09 4A 00 F0 07 F8 01 1C 08 4A 60 00 12 18
0x08251C80        11 80 01 34 E6 E7 10 47 3F BD C0 46 C0 70 03 02
0x08251C90        86 42 02 02 BE 70 03 02 E9 FB 03 08 C4 70 03 02


I've taken the code and put in comments on each line summarizing what I understand each line to do. Am I mistaken? Am I completely wrong?

Spoiler:

Code:

//---------------
#org 0x2514D0
lock
faceplayer
msgbox 0x82515D0 MSG_YESNO //"Would you like to know the\npotent..."
compare LASTRESULT 0x0
if 0x1 goto 0x8251570
setvar 0x8003 0x1
setvar 0x8004 0x0
callasm 0x8251C51
buffernumber 0x0 0x8005
buffernumber 0x1 0x8006
msgbox 0x8251610 MSG_NORMAL //"HP: [buffer1] IVs\nAttack: [buffer..."
buffernumber 0x0 0x8007
buffernumber 0x1 0x8008
msgbox 0x8251630 MSG_NORMAL //"Defence: [buffer1] IVs\nSpeed: [bu..."
buffernumber 0x0 0x8009
buffernumber 0x1 0x800A
msgbox 0x8251650 MSG_NORMAL //"Special Attack: [buffer1] IVs\nSpe..."
end

//---------------
#org 0x251570

//---------
// Strings
//---------
#org 0x2515D0
= Would you like to know the\npotential of your Pokémon?

#org 0x251610
= HP: [buffer1] IVs\nAttack: [buffer2] IVs

#org 0x251630
= Defence: [buffer1] IVs\nSpeed: [buffer2] IVs

#org 0x251650
= Special Attack: [buffer1] IVs\nSpecial Defence: [buffer2] IVs.




Everything I have there follows the implementation instructions to a T, yet the memory still shows

Code:

0x020370BD        00 01 00 00 00 19 00 19 00 19 00 19 00 19 00 19
0x020370CD        00 19 00 01 00 02 00 04 00 00 00 00 00 FF 00 01


and just to make sure it wasn't a statistical fluke, I ran the same script with 5 or so more randomly encountered pokemon and ran them through an IV calculator. Each time, the HP IV shown by the ASM was correct, but then copied it to every other variable set in the script.

Blah October 16th, 2019 6:12 PM

Hi, first of all I'd like to apologize for the mistake. I haven't tested that code, and it's in assembly so a semantic error here and there tend to be around for some of them. A quick skim through it, it does seem like there is a minor error.

Quote:

add r1, r1, #0x27 @IV
This line of code I assume gets the HP IV, however, it will always be 0x27, and therefore not get any subsequent IVs.
That line should be replaced by:
Quote:

add r1, r4, #0x27
If the assembler says the above line is invalid, try:
Quote:

add r1, r1, r4
add r1, r1, #0x27
Hopefully that does the trick.

jvhbv October 17th, 2019 4:02 AM

Quote:

Originally Posted by FBI (Post 10078576)
Hi, first of all I'd like to apologize for the mistake. I haven't tested that code, and it's in assembly so a semantic error here and there tend to be around for some of them. A quick skim through it, it does seem like there is a minor error.

Code:

add r1, r1, #0x27 @IV


This line of code I assume gets the HP IV, however, it will always be 0x27, and therefore not get any subsequent IVs.
That line should be replaced by:

Code:

add r1, r4, #0x27


If the assembler says the above line is invalid, try:

Code:

add r1, r1, r4
add r1, r1, #0x27


Hopefully that does the trick.

Hey FBI, thanks for the reply, and I'm happy to say that
Code:

add r1, r1, r4
add r1, r1, #0x27


did the trick perfectly! It seems to be displaying the correct IVs for each stat now and isn't causing any issues. Again, thank you so much for the help.

Flarbley October 26th, 2019 4:52 PM

I'm having a problem with shiny odds, compiled all three parts but when I clear the textbox after receiving my starter the game resets, any idea what I did wrong?

ghoulslash October 28th, 2019 11:20 AM

[FR] Map Music Loader

This small hack loads map music by a variable rather than the map header (if the variable is set to a non-zero value). just set MUSIC_VAR to some variable value and compile, insert into free space, and overwrite the corresponding bytes at 0x55D70 (found at top of routine).

In a script, set the variable to a specific song ID, and the game will play that song ID after trainerbattles and warps (perhaps others that I have not thought of or tested).

Spoiler:
Code:

.text
.align 2
.thumb
.thumb_func
.global LoadMapMusic
/*
load song regardless of map default

hook at 55D70 via r0
        aka 00 48 00 47 xx+1 xx xx 08
*/

.equ MUSIC_VAR, 0x4XXX        @some free variable in save block

Main:
        push {r1-r3}
        ldr r0, .var
        bl GetVarVal
        pop {r1-r3}
        cmp r0, #0x0
        beq LoadFromMapHeader
        pop {pc}

LoadFromMapHeader:
        ldrb r0, [r1]
        ldr r2, =(0x08055D78 +1)
        bx r2

GetVarVal:
        ldr r2, =(0x0806e568 +1)
        bx r2

.align 2
.var: .word MUSIC_VAR




Enjoy!

Tacobell24 December 7th, 2019 4:54 AM

Quote:

Originally Posted by DarkPsychic (Post 9844336)
Pokemon LoathingFriendship Evolution:
Code:

.text
.align 2
.thumb
.thumb_func
.global loathFriendship

main:
push {r0-r7}
add r0, r6, r7
lsl r0, r0, #0x3
add r0, r2, r0
add r3, r0, r3
ldrb r2, [r3, #0x2]
mov r0, r8
bl decrypt
mov r11, r0
pop {r0-r7}
mov r1, r11
cmp r1, #0x10
blo max_lowhappy
b exit

max_lowhappy:
mov r10, r3
pop {r0-r7}
mov r1, r10
ldr r0, evolution_loc
bx r0

exit:
pop {r0-r7}
ldr r0, no_evo
bx r0

decrypt:
push {r0-r7}
mov r1, #0x20
ldr r2, decryptpoke
bx r2

.align 2
no_evo: .word 0x08043111
evolution_loc: .word 0x0804310D
decryptpoke: .word 0x0803FBE9


The Pokemons happiness must be between 0-10 to trigger the evolution.
To insert follow instructions in this thread.

I hope some find this useful.
I thought about trade evolution basically being just this.
A Pokemon so depressed it evolves...

It took me 50+ pages to find this. But thanks brotato. This is exactly what I need 👍

BluRose December 17th, 2019 12:49 PM

headbutt trees (fire red)
https://i.imgur.com/OOQuzFF.png

so basically i was talking with petuh 2 days ago about how rusty i probably am at strict assembly

so here i am! i made a thing

Spoiler:
Code:

@ the whole headbutt tree system
@ it implements jpan's behavior byte hack as well as the headbutt system in the space that the old routine took up.  when he said it was overly inefficient, he meant it!
@ compile this and then go to the offset 0x806D1F0 in the resulting .bin output.  copy everything there until the next block of zeros.  paste it to offset 0x6D1F0 in your rom.
@ there are various parameters you can play around with.  most of these are primarily the tables halfway through this.
@ i tried to comment it throughout!

@ now, in amap, there's the one field that is primarily used in wild encounter spots.  it's 2 when wild grass and 4 when surfing on water encounters.
@ because we won't be walking on the headbutt tree, we can use this field to our advantage.
@ cur_mapdata_block_get_field_at(s16 x, s16 y, u8 field) references a bunch of other routines, but eventually, it boils down to a bunch of preset fields or'd with the header info.
@ the first is 0x1FF, or the 9 least significant bits.  this is the behavior byte itself.
@ the second is 0x3E00, or the next 5 bits in terms of significance.  this allows for 2^5 (32) bits for use for our table.
@ note that the entry entered in this table should be multiplied by 2 because of the way that amap (incorrectly) displays the data.  this allows the code below to reference it properly.
@ screens are given in the post.

.text
.align 2
.thumb
.thumb_func

.org 0x08044EC8

@ returns r0 = pseudorandom number
random:
        .hword 0x4A04

.org 0x08058F48

@ returns r0 = (metatile behavior long or blockinfo_bit_masks[field]) >> blockinfo_bit_right_shift_num[field]
cur_mapdata_block_get_field_at: @ (s16 x, s16 y, u8 field)
        push {r4, lr}

.org 0x0806CE38

@ writes the next pos and height to the pointer given in r0
player_get_next_pos_and_height: @ (*[s16 x, s16 y, u8 height])
        push {r4, r5, lr}

.org 0x0806D1F0

@ this assembly routine is a modded version of jpan's behavior byte hack that decreases space required for the table while slightly increasing what's needed for the code
onpress_a_get_script_tile:
        lsl r1, r1, #0x18
        lsr r0, r1, #0x18
        cmp r0, #0x80
        blt _not_governed @ we don't care about entries less than h80
        sub r0, r0, #0x80
        lsl r0, r0, #0x2
        ldr r1, behavior_table_ref @ load the table pointer here
        add r0, r0, r1
        ldr r0, [r0] @ load the script pointer here
        b _return_loc
_not_governed:
        mov r0, #0
_return_loc:
        mov pc, lr

.align 2

behavior_table_ref:
        .word behavior_table

behavior_table: @ for the playerfacing behaviors
        .word 0
        .word 0x081A7606 @ bookshelf
        .word 0x081A760F @ market shelf
        .word 0x081A6955 @ pc
        .word 0
        .word 0x081A6C32 @ town map
        .word 0x081A764E @ tv
        .word 0x081A76E7 @ pokemon center
        .word 0x081A76DE @ pokemon mart
        .word 0x081A7657 @ cabinet
        .word 0x081A7660 @ cooking smells great!
        .word 0x081A7669 @ dresser
        .word 0x081A7672 @ snacks
        .word 0x081BBFD8 @ wireless
        .word 0x081BB8A7 @ not available
        .word 0x081A7702 @ questionnaire
        @ 0x90
        .word 0x081A7618 @ fridge
        .word 0x081A76F0 @ indigo plateau
        .word 0x081A76F9 @ indigo plateau 2
        .word 0x081A763C @ blueprint
        .word 0x081A767B @ pokemon pics
        .word 0x081A7684 @ complex machine.  better not touch it!
        .word 0x081A768D @ telephone
        .word 0x081A762A @ complex numbers
        .word 0x081A7696 @ ads
        .word 0x081A769F @ tasty food
        .word 0x081A76A8 @ trash can
        .word 0x081A76B1 @ cup
        .word 0
        .word 0
        .word 0x081A76CC @ lights
        .word 0x081A76D5 @ tools
        @ 0xA0
        .word 0x081A7633 @ random machine
        .word 0x081A7621 @ consoles
        .word 0x081A7645 @ robbery
        .word 0x081C549C @ timer
@ now, i personally added headbutt_script here, but it can go in any one of the zeros above.  just make sure that you note the entry correctly!
        .word headbutt_script @ headbutt tree behavior byte (0xA4)

.equ table_amount, 3
.equ terminate, 0xFE @ only rule here is that it isn't a pokemon you want to appear in a tree.  if you wanted to use pokemon index 254, go for it i guess, but change this
.equ var_begin, 0x020270B8

headbutt_tree:
        push {r4-r6, lr}
        ldr r0, var_8000 @ position_ptr
@ the below branch will store the position in front of the player's x in var_8000, y in var_8001, and the height in the most significant byte of var_8002
@ this is because it writes to the pointer in r0
        bl player_get_next_pos_and_height
        ldr r4, var_8000
        ldrh r0, [r4] @ x
        ldrh r1, [r4, #2] @ y
        mov r2, #1 @ field id
@ the field entry 1 is 5 bits of the second behavior byte thing in advancemap.  this means we can have up to 32 headbutt tables denoted by even numbers from 0-64 in amap.
@ this is explained further above
        bl cur_mapdata_block_get_field_at
        lsl r0, r0, #0x18
        lsr r4, r0, #0x18 @ r4 = table number
@ part below catches invalid tables and prevents them from working
        cmp r4, #table_amount
        bge _nothingfell
        ldr r0, tableoftables_ref
        lsl r1, r4, #2 @ r1 = table number * 4
        ldr r4, [r0, r1] @ r4 = table pointer to the relevant one
@ below, generate a random number less than 100 to emulate chance
        bl random @ r0 = random()
        mov r1, #100
        bl __umodsi3 @ r0 = r0 % 100
        mov r5, #0 @ set up the loop counter
        ldr r6, terminate_byte

@ at this point, r0 = random() % 100, r4 = table pointer, r5 = loop counter, r6 = terminator
_loop:
        mov r1, #7 @ 7 being the size of each entry
        mul r1, r5, r1
        add r3, r4, r1 @ store the current entry's pointer in r3
        ldrh r2, [r3] @ seems to be very finicky at times, loading random values from the surroundings?
        lsl r2, r2, #0x10
        lsr r2, r2, #0x10
        cmp r2, r6
        beq _nothingfell
        ldrb r2, [r3, #6] @ load the chance of this entry into r2
        cmp r0, r2
        ble _somethingfell
        add r5, r5, #1 @ increment the loop counter
        b _loop

_somethingfell:
        mov r4, r3
@ at this point, r4 is the table entry we care about.  don't touch it
        bl random @ generate a new random number
        @ r0 = random()
        ldrb r2, [r4, #2] @ load the lower level
        ldrb r1, [r4, #3] @ load the higher level
        sub r1, r1, r2 @ subtract the lower level from the higher level, store it as the parameter for modulo
        bl __umodsi3
        @ r0 = random() % (highlevel - lowlevel)
        ldrb r2, [r4, #2] @ load the lower level again bc umodsi ****in w the value
        add r1, r0, r2 @ level parameter
        ldrh r0, [r4] @ species parameter
        ldrh r2, [r4, #4] @ item parameter
        bl create_scripted_mon
        ldr r0, var_8000
        mov r1, #0
        strh r1, [r0, #0x18] @ store 0 into var_800D
        b _end

_nothingfell:
        ldr r0, var_8000
        mov r1, #0xFF
        strh r1, [r0, #0x18] @ store 0xFF into var_800D

_end:
        pop {r4-r6}
        pop {r1} @ this is the return method used by many of the script stuff so
        bx r1

.align 2

@ used to store the position struct
var_8000:
        .word (var_begin + (0x8000 * 2))

terminate_byte:
        .word terminate

tableoftables_ref:
        .word tableoftables

@ note that, in order to expand the tables, you need to add another entry here for each of the tables.
tableoftables:
        .word lowencounter
        .word medencounter
        .word highencounter

@ bunch of defines to make the below better readable
.equ caterpie, 10
.equ metapod, 11
.equ butterfree, 12
.equ weedle, 13
.equ kakuna, 14
.equ beedrill, 15
.equ exeggcute, 102
.equ exeggutor, 103
.equ tangela, 114
.equ pinsir, 127
.equ snorlax, 143
.equ pineco, 204
.equ heracross, 214

@ a sample item
.equ brightpowder, 179

@.org 0x08XXXXXX @ optional repoint of the tables below in case you want a higher amount of pokemon.

@ here's the table format:
@ [2 bytes - species] [1 byte - lower level] [1 byte - higher level] [2 bytes] - item it can hold] [1 byte - chance it will appear]
@ the chance byte at the very end is subtracted from the previous entry in the tables in order to get that specific entry's chance of showing up.
@ sample entries are below:

lowencounter:
        .hword weedle                @ species
        .byte 5                                @ lower level
        .byte 7                        @ higher level
        .hword brightpowder @ item
        .byte 20                        @ chance

        .hword kakuna                @ species
        .byte 12                        @ lower level
        .byte 15                        @ higher level
        .hword 0                        @ no item
        .byte 40                        @ chance:  40 - 20 (weedle's entry above) = 20

        .hword beedrill
        .byte 60
        .byte 70
        .hword brightpowder
        .byte 100                        @ chance:  100 - 40 (kakuna's entry above) = 60

        .hword terminate

@ this table represents an instance where we don't have to get a pokemon 100% of the time.  the code handles it!
medencounter:
        .hword caterpie
        .byte 5
        .byte 7
        .hword brightpowder
        .byte 35

        .hword metapod
        .byte 12
        .byte 15
        .hword 0
        .byte 45

        .hword butterfree
        .byte 60
        .byte 70
        .hword brightpowder
        .byte 50

        .hword terminate
        @ 50% of the time, a pokemon won't fall.

highencounter:
        .hword exeggcute
        .byte 10
        .byte 12
        .hword 0
        .byte 40

        .hword tangela
        .byte 20
        .byte 25
        .hword 0
        .byte 60

        .hword heracross
        .byte 17
        .byte 22
        .hword brightpowder
        .byte 90

        .hword snorlax
        .byte 50
        .byte 60
        .hword brightpowder
        .byte 100

        .hword terminate

@ optional insert of the script.  there's still about hB0 bytes left over after the script is inserted, allowing for about 19 EXTRA mon entries (on top of the 10 there already)
@ repoint if so desired.  the assembly will take care of it!
@.org 0x08XXXXXX

.equ headbutt, 0x1D
.equ lastresult, 0x800D

headbutt_script: @ this is included here for the dynamic compiling so that you don't have to care.  feel free to edit it though
        .byte 0x6A

        .byte 0x7C
        .hword headbutt

        .byte 0x21
        .hword lastresult
        .hword 0x06

        .byte 0x06
        .byte 0x01
        .word no_headbutt_in_party

        .byte 0x9D
        .byte 0x00
        .hword lastresult

        .byte 0x7F
        .byte 0x00
        .hword lastresult

        .byte 0x82
        .byte 0x01
        .hword headbutt

        .byte 0x0F
        .byte 0x00
        .word text_headbutt_in_party
        .byte 0x09
        .byte 0x05

        .byte 0x21
        .hword lastresult
        .hword 0x00

        .byte 0x06
        .byte 0x01
        .word said_no

        .byte 0x0F
        .byte 0x00
        .word text_poke_used_atk
        .byte 0x09
        .byte 0x04

        .byte 0x68

        .byte 0x9C
        .hword 0x2

        .byte 0x27

@ the callasm is here
        .byte 0x23
        .word headbutt_tree + 1

@ this comparison here prevents the dowildbattle from happening if lastresult is 0xFF (the chance was higher than the highest chance defined in the table)
@ lastresult's modification is in the assembly above
        .byte 0x21
        .hword lastresult
        .hword 0xFF

        .byte 0x06
        .byte 0x01
        .word tree_was_undisturbed

        .byte 0x0F
        .byte 0x00
        .word text_exclamation
        .byte 0x09
        .byte 0x06

        .byte 0xB7

        .byte 0x6C

        .byte 0x02

        .byte 0xFF

no_headbutt_in_party:
        .byte 0x0F
        .byte 0x00
        .word text_cant_headbutt
        .byte 0x09
        .byte 0x06

        .byte 0x6C

        .byte 0x02

        .byte 0xFF

said_no: @ closes the textbox
        .byte 0x68

        .byte 0x6C

        .byte 0x02

        .byte 0xFF

tree_was_undisturbed:
        .byte 0x0F
        .byte 0x00
        .word text_tree_undisturbed
        .byte 0x09
        .byte 0x06

        .byte 0x6C

        .byte 0x02

        .byte 0xFF

text_headbutt_in_party: @ This tree can be headbutted! Would you like to use headbutt?
        .byte 0xCE
        .byte 0xDC
        .byte 0xDD
        .byte 0xE7
        .byte 0x00
        .byte 0xE8
        .byte 0xE6
        .byte 0xD9
        .byte 0xD9
        .byte 0x00
        .byte 0xD7
        .byte 0xD5
        .byte 0xE2
        .byte 0x00
        .byte 0xD6
        .byte 0xD9
        .byte 0x00
        .byte 0xDC
        .byte 0xD9
        .byte 0xD5
        .byte 0xD8
        .byte 0xD6
        .byte 0xE9
        .byte 0xE8
        .byte 0xE8
        .byte 0xD9
        .byte 0xD8
        .byte 0xAB
        .byte 0xFE
        .byte 0xD1
        .byte 0xE3
        .byte 0xE9
        .byte 0xE0
        .byte 0xD8
        .byte 0x00
        .byte 0xED
        .byte 0xE3
        .byte 0xE9
        .byte 0x00
        .byte 0xE0
        .byte 0xDD
        .byte 0xDF
        .byte 0xD9
        .byte 0x00
        .byte 0xE8
        .byte 0xE3
        .byte 0x00
        .byte 0xE9
        .byte 0xE7
        .byte 0xD9
        .byte 0x00
        .byte 0xC2
        .byte 0xD9
        .byte 0xD5
        .byte 0xD8
        .byte 0xD6
        .byte 0xE9
        .byte 0xE8
        .byte 0xE8
        .byte 0xAC
        .byte 0xFF
        .byte 0x00
        .byte 0xFF

text_poke_used_atk: @ [string1] used [string2]!
        .byte 0xFD
        .byte 0x02
        .byte 0x00
        .byte 0xE9
        .byte 0xE7
        .byte 0xD9
        .byte 0xD8
        .byte 0x00
        .byte 0xFD
        .byte 0x03
        .byte 0xAB
        .byte 0xFF
        .byte 0x00
        .byte 0xFF

text_exclamation: @ Whoa!
        .byte 0xD1
        .byte 0xDC
        .byte 0xE3
        .byte 0xD5
        .byte 0xAB
        .byte 0xFF
        .byte 0x00
        .byte 0xFF

text_cant_headbutt: @ This tree looks like Pokémon can live in it.
        .byte 0xCE
        .byte 0xDC
        .byte 0xDD
        .byte 0xE7
        .byte 0x00
        .byte 0xE8
        .byte 0xE6
        .byte 0xD9
        .byte 0xD9
        .byte 0x00
        .byte 0xE0
        .byte 0xE3
        .byte 0xE3
        .byte 0xDF
        .byte 0xE7
        .byte 0x00
        .byte 0xE0
        .byte 0xDD
        .byte 0xDF
        .byte 0xD9
        .byte 0x00
        .byte 0xCA
        .byte 0xE3
        .byte 0xDF
        .byte 0x1B
        .byte 0xE1
        .byte 0xE3
        .byte 0xE2
        .byte 0x00
        .byte 0xD7
        .byte 0xD5
        .byte 0xE2
        .byte 0xFE
        .byte 0xE0
        .byte 0xDD
        .byte 0xEA
        .byte 0xD9
        .byte 0x00
        .byte 0xDD
        .byte 0xE2
        .byte 0x00
        .byte 0xDD
        .byte 0xE8
        .byte 0xAD
        .byte 0xFF
        .byte 0x00
        .byte 0xFF

text_tree_undisturbed: @ But the tree remained undisturbed...
        .byte 0xBC
        .byte 0xE9
        .byte 0xE8
        .byte 0x00
        .byte 0xE8
        .byte 0xDC
        .byte 0xD9
        .byte 0x00
        .byte 0xE8
        .byte 0xE6
        .byte 0xD9
        .byte 0xD9
        .byte 0x00
        .byte 0xE6
        .byte 0xD9
        .byte 0xE1
        .byte 0xD5
        .byte 0xDD
        .byte 0xE2
        .byte 0xD9
        .byte 0xD8
        .byte 0xFE
        .byte 0xE9
        .byte 0xE2
        .byte 0xD8
        .byte 0xDD
        .byte 0xE7
        .byte 0xE8
        .byte 0xE9
        .byte 0xE6
        .byte 0xD6
        .byte 0xD9
        .byte 0xD8
        .byte 0xAD
        .byte 0xAD
        .byte 0xAD
        .byte 0xFF
        .byte 0x00

.org 0x080A029C

create_scripted_mon: @ (u16 species, u8 level, u16 item)
        push {r4-r7, lr}

.org 0x081E4684

@ returns r0 = dividend % divisor
__umodsi3: @ (u16 dividend, u16 divisor)
        cmp r1, #0


this is also downloadable here.

this implements a modified jpan's behavior byte hack so that it takes up far less space (only affects the behavior byte entries it governs). it then adds a new entry, a pointer to the script that's also dynamically compiled. by default, this new one is behavior byte 0xA4!

in its purest form, you need to configure the tables and then compile it using your favorite asm compiling software. go to 0x806D1F0 and copy it until the zeros are reached. note that you will need to edit the tables in there as you so desire.
each new table needs to be referenced in tableoftables so that the code will read it.
copy that over to 0x6D1F0 in your fire red v1.0 rom. that's it! all you have to do.

tables are split into entries for each pokemon, each 7 bytes:
[2 bytes] - species
[1 byte] - lower level
[1 byte] - higher level
[2 bytes] - item
[1 byte] - chance of appearing (when subtracted from the previous entry's chance entry, it gives the specific entry's chance of appearing

this will generate a pokemon of the defined species with a random level between lower level and higher level with the item in the table.

in editing the tables, there's an .equ for table_amount. edit that to accomodate the new tables; it's currently at 3.

now, i tried to label it as well as i could. ask me any questions you have on the code ahaha

this system works by loading separate tables based on the second byte in advancemap labeled "behavior byte" when given a certain behavior byte. you know, this one:

https://i.imgur.com/iJTYSBk.png

in classic amap fashion, this is rather wrong

what happens in the code is that all 4 of those are considered one 4-byte word and the game retrieves the values it wants in various fields

everything that wants to retrieve a value from this area eventually references 0x8058F1C, or blockinfo_get_field in knizz's idb.
it takes the blockinfo and a field value and returns the value of that field.

blockinfo_get_field uses the words at 352EF0, or's it w the blockinfo (the 4 bytes from the block editor in amap), and returns the result shifted right by the corresponding entry in the byte array at 352F10. this results in a neat return value.

field 0 is the behavior byte field, like the main one, but is also 1 bit from the second byte (it's 9 bits long)
the one that is kind of labeled in amap

field 1 is then part of the second byte labeled as a behavior byte. this is the field i used in this to try not to rewrite anything too extensively
within the second byte, we split it down into bits:

[7] [6] [5] [4] [3] [2] [1] [0]

field 1 is bits 1-5 (NOT zero!). they are bold in the above example. this is why the grass is 2, and the water is 4; the values for field 1 for these respective values are actually 1 and 2!

what this practically means? the second byte is the table number * 2. so if i wanted to use table 3 (the 4th table because of 0-indexing), then i would put 6 in that second field.
for ease of editing, a bunch of equ's for various bug pokemon are included in the file. brightpowder is also the only defined item, but that can be changed if you so desire.

so that tree in the amap screen up there? it's a headbutt tree (behavior byte 0xA4) that accesses table 2.

ONE NOTE ON THIS

you have 0x358 bytes to work with here. if you go to 0x806D1F0 in the compiled binary and select all those bytes and the size is over 0x358, then you will be overwriting surfing code.
you have up to 0x6D548.
this supports easy repointing, be it the tree tables or the script. either way, just uncomment one of the org's and change it to the place where free space is.

with all that done, you should have a new headbutt tree system in your game! see you next time~



EDIT: also i have half a mind to take thread ownership. i'll start compiling a list of everything here and links to them w descriptions when i have free time tomorrow and then ask if i can take over after everything is compiled

~Andrea December 22nd, 2019 2:30 AM

Colored Stats based on Nature[RUBY]
https://i.imgur.com/sNVysl4.png
To implement this feature, only one routine is needed:
Spoiler:

Code:

.THUMB
.ALIGN 2

PUSH {R0-R7}
MOV R0, R5
PUSH {R1-R7}
BL GET_NATURE
POP {R1-R7}
LDR R1, = 0x081FD070
MOV R2, #5
MUL R0, R2
ADD R6, R0, R1

MOV R4, #1
LOOP:
MOV R0, R5

MOV R2, PC
ADD R2, R2, #0x74
LDRB R1, [R2, R4]
MOV R7, R1

GET_DATA:
PUSH {R1-R7}
BL GET_MON_DATA
POP {R1-R7}
MOV R1, R0
LDR R0, .BUFFER
PUSH {R0-R7}
BL INT_TO_DEC
POP {R0-R7}

MOV R0, R4
MOV R1, #3
PUSH {R1-R7}
BL MOD
POP {R1-R7}
LSL R3, R0, #1
ADD R3, R3, #7

LDR R0, .BUFFER
MOV R1, #0xF

MOV R2, #22
CMP R4, #3
BLT COLORED

ADD R2, R2, #9

COLORED:
SUB R7, R7, #0x3B
LDRB R7, [R6, R7]

CMP R7, #0
BEQ PRINT_STR
CMP R7, #0xFF
BEQ LOWER

UPPER:
MOV R1, #0xB
B PRINT_STR

LOWER:
MOV R1, #0xC

PRINT_STR:
PUSH {R0-R7}
MOV R4, #36
BL PRINT
POP {R0-R7}
ADD R4, R4, #1
CMP R4, #6
BNE LOOP
POP {R0-R7}

LDR R0, = 0x080A0048+1
BX R0

GET_NATURE:
LDR R1, = 0x0803F464+1
BX R1

PRINT:
LDR R4, = 0x080A1F48+1
BX R4

GET_MON_DATA:
LDR R2, = 0x0803CB60+1
BX R2

INT_TO_DEC:
LDR R2, = 0x08006DDC+1
BX R2

MOD:
LDR R2, = 0x081E0F08+1
BX R2

.ALIGN 2
.BUFFER:        .WORD        0x020231CC
.TABLE:                .BYTE        0x3A
                .BYTE        0x3B
                .BYTE        0x3C
                .BYTE        0x3E
                .BYTE        0x3F
                .BYTE        0x3D
                .HWORD        0



After compiling the routine in a free offset, go to 0x09FFBC and overwrite the bytes with 00480047xxxxxx08.
Instead of the XX, will be entered the offset of previous routine + 1 and in Little Endian format (example: 08123456 -> 57 34 12 08).

eMMe97 January 8th, 2020 2:13 AM

Quote:

Originally Posted by Koople (Post 9924710)
Side Quest Menu [FR]

This hack converts the PC item storage menu into a side quest menu, or task list, etc.

Here is the repository, the compilation instructions are included in the readme. You will need to define your own parameters/ram in src/headers/defs.asm and create your own tables of string pointers for all of the quest names, descriptions, item images, and quest details. I kept the item image part to allow hackers to include items that might be symbolic of their quest, eg. a scroll or key or pokeball.

To use in a script (XSE)
Code:

writebytetooffset 0x1 <your questflag ram in src/headers/defs.asm>
fadescreen 0x1
callasm 0x80EBCD9
waitstate


Enjoy! And please let me know of any bugs.

I have a lot of problem with this Side Quest Menu...I make some screens

Item Menu doesn't show the item name

https://i.imgur.com/6jrzJI6.png

Item menu without item show ?????? 0x0 item

https://i.imgur.com/qsOA0SB.png

Quest Menu doesn't show quest name with activate flag ON

https://i.imgur.com/qwwcQAx.png

Neon Skylar January 8th, 2020 7:49 AM

This is the code to show icon on pause menu for Ruby by Andrea.. I need help to insert it on emerlad

.THUMB
.ALIGN 2
@08071174 00490847XXXXXX08
@080711C8 MOVS R0, #0x16 @coordinata x
@08071208 lunghezza cursore
@0807120E posizione X cursore

PUSH {R0-R7}
LDR R1, = 0x06008020
LDR R0, = 0x087200D0
MOV R2, #0x15
LSL R2, #4
SWI 0xC

LSL R2, #2
ADD R0, R2

MOV R3, #1
LSL R3, #10

LDR R1, = 0x0202EC48
MOV R2, #8
SWI 0xC
LDR R4, = 0x0202FEB3
LDRB R4, [R4]
CMP R4, #0x16
BNE ICONE
ADD R1, R1, R3
SWI 0xC

ICONE:
MOV R6, #0

MOV R0, #1
LSL R0, #11
ADD R0, #1
BL CHECKFLAG
CMP R0, #0
BEQ PARTY

ADD R6, #1
MOV R0, #0
MOV R1, #0
BL SPAWN

PARTY:
MOV R0, #1
LSL R0, #11
BL CHECKFLAG
CMP R0, #0
BEQ ALTRO

MOV R0, #1
ADD R6, #1
CMP R6, #2
BEQ CONTROLLO
MOV R0, #0
CONTROLLO:
MOV R1, #1
BL SPAWN

ALTRO:
LDR R5, = 0x0202E8FD
LDRB R5, [R5]

MOV R7, #2
LOOP2:
MOV R0, R6
MOV R1, R7
BL SPAWN
ADD R6, #1
ADD R7, #1
CMP R6, R5
BNE LOOP2

FINE:
POP {R0-R7}
POP {R4-R7,PC}

SPAWN:
LSL R0, #7
LDR R2, = 0x0600F8A8
ADD R0, R2
MOV R3, #6
MUL R1, R3
ADD R1, #1
MOV R2, #0xC0
LSL R2, #8
ADD R1, R2
MOV R2, #0
MOV R3, #0
LOOP:
STRH R1, [R0]
ADD R0, #2
ADD R1, #1
ADD R2, #1
CMP R2, #3
BNE LOOP
ADD R0, #0x3A
MOV R2, #0
ADD R3, #1
CMP R3, #2
BNE LOOP
BX LR

CHECKFLAG:
PUSH {R0}
LDR R0, = 0x08069341
MOV R10, R0
POP {R0}
BX R10

Ruux January 8th, 2020 8:02 PM

I want to change the amount of experience given by pokemon in Fire Red. I could go through and manually update the values of each pokemon, but I'm just wondering if anybody knows where to find the offset where the experience formula is.

Dr. POP January 15th, 2020 5:30 AM

Quote:

Originally Posted by FBI (Post 8517719)

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

Spoiler:
How to insert:

Compile into free space the following routine:
Spoiler:

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, r0, #0x1
        ldrb r1, [r0]
        cmp r1, #0x6 @limit of storage. Change depending on your space situation
        beq end
        add r0, r0, #0x1
        mov r2, #0x50
        cmp r1, #0x0
        beq skipline
        sub r1, r1, #0x1
        mul r1, r1, r2
        add r0, r0, r1 @destination
        ldr r1, =(0x20370C0)
        ldrb r1, [r1]
        ldr r2, .PARTY
        mov r3, #0x64
        mul r1, r1, r3
        add r1, r1, r2 @source
        mov r2, #0x50 @size
        ldr r3, =(0x8040B08 +1) @func
        bl linker
        @need to fix up Player's party slots
        ldr r1, =(0x20370C0)
        ldrb r1, [r1]
        cmp r1, #0x5
        beq writeLastZero
        mov r2, #0x5
        sub r2, r2, r1
        mov r3, #0x64
        mul r2, r2, r3 @size
        ldr r0, .PARTY
        mul r1, r1, r3
        add r0, r0, r1 @dest
        add r3, r3, r0
        mov r1, r3      @src
        ldr r3, =(0x8040B08 +1) @func
        bl linker

writeLastZero:
        ldr r0, =(0x2024478)
        mov r1, #0x0
        mov r2, #0x64
        ldr r3, =(0x81E5ED8 +1)
        bl linker

correctCounters:
        ldr r0, .STORAGE
        sub r0, r0, #0x1
        ldrb r2, [r0]  @pks in storage counter
        ldr r1, =(0x2024029)
        ldrb r3, [r1] @pks in party
        add r2, r2, #0x1
        strb r2, [r0]
        sub r3, r3, #0x1
        strb r3, [r1]
        b end

addParty:
        ldr r0, =(0x2024029)
        ldrb r0, [r0]
        cmp r0, #0x6
        beq end
        ldr r1, .PARTY
        mov r2, #0x64
        mul r0, 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, r1, r2
        add r1, r1, r3 @source
        ldr r3, =(0x8040B08 +1) @func
        bl linker
        @update stats
        mov r0, r4
        ldr r3, =(0x803E47C +1)
        bl linker
        @adjust the storage
        ldr r0, =(0x20370C0)
        ldrb r0, [r0]
        cmp r0, #0x5 @storage limit minus 1
        beq writeZero
        mov r2, #0x5
        sub r2, r2, r0
        mov r3, #0x50
        mul r2, r2, r3 @size
        ldr r1, .STORAGE
        mul r0, r0, r3
        add r0, r0, r1 @dest
        add r3, r3, r0
        mov r1, r3      @src
        ldr r3, =(0x8040B08 +1) @func
        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, =(0x81E5ED8 +1)
        bl linker

updateCounters:
        ldr r0, .STORAGE
        sub r0, r0, #0x1
        ldrb r2, [r0]
        ldr r1, =(0x2024029)
        ldrb r3, [r1]
        sub r2, r2, #0x1
        strb r2, [r0]
        add r3, r3, #0x1
        strb r3, [r1]

end:
        pop {r0-r4, pc}       

linker:
        bx r3       

.align 2

.FROM:
        .word 0x20270B8 + (0x8000 *2)

.STORAGE:
        .word 0x203C001 @storage location

.PARTY:
        .word 0x2024284 @player's party




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:

PKSV script.
Code:

#dyn 0x740000
#org @start
lock
faceplayer
copybyte 0x20370D0 0x203C000 ' storage count into last result
compare LASTRESULT 0x0
if == jump @putOnly
msgbox @add
callstd MSG_YESNO 'want to take?
compare LASTRESULT 0x1
if == jump @addParty
jump @putOnly

#org @putOnly
countpokemon
copyvar 0x8000 0x800D
compare 0x8000 0x1
if <= jump @greetings
msgbox @put
callstd MSG_YESNO 'want to put?
compare LASTRESULT 0x1
if == jump @addStorage
msgbox @exit
callstd MSG_NORMAL
release
end

#org @addStorage
setvar 0x8000 0x1
special 0x9F
waitspecial
countpokemon
compare LASTRESULT 0x8004
if < jump @noSelection
callasm 0x[routine +1]
msgbox @gave
callstd MSG_NORMAL
release
end

#org @addParty
setvar 0x8000 0x0
countpokemon
compare LASTRESULT 0x6
if == jump @fullP
msgbox @store
callstd MSG_NORMAL
setvar 0x8004 0x0 'gotta rework this to work a better way
callasm 0x[routine +1]
fanfare 0x101
msgbox @complete
callstd MSG_NORMAL
release
end

#org @greetings
msgbox @hello
callstd MSG_NORMAL
release
end

#org @fullP
msgbox @full
callstd MSG_NORMAL
release
end

#org @noSelection
msgbox @exit
callstd MSG_NORMAL
release
end

#org @full
= You're party is full!

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

#org @complete
= I gave it back.

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

#org @gave
= Thanks for giving me this.

#org @exit
= Alright, next time then.

#org @add
= Want your Pokemon back?

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




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

It seems that the memory location for the storage system (0x203C000) has been used already by another ASM routine my ROM base (Leon/UltimaSoul's) has implemented. I cannot find which exact memory locations are free, but I figured the best shot would be 0x203CC00.

I have tried to amend the routine by simply changing the memory location in the routine under .STORAGE. However, unfortunately the game freezes when the ASM routine is called. What is the best way to relocate the storage system to free memory space? Am I missing something obvious? Thanks in advance for any help!

Zeturic February 1st, 2020 10:47 AM

Functional Pokérus [FR]

This allows Pokérus to be caught randomly, spread between Pokémon, and (optionally) cured. It also includes a
special
for checking if a Pokémon in the player's party has Pokérus, for use in a Nurse Joy script.

Curing Pokérus is based on walking around, not on an RTC.

Several of the Pokérus related functions included here were lifted directly (or with small modifications) from pokeemerald.

Let me know if you have issues.

Zeturic February 8th, 2020 7:36 PM

More Options For In-Game Trades [FR]

It allows you to have In-Game Trades that come with/at/in:
  • Static levels, like in newer games
  • Pokérus
  • Custom movesets
  • PP bonuses
  • Poké Balls other than the default

You can also use it as a sort of trade editor, because it extracts the in-game trade data from your ROM in a compilable form you can modify.

Let me know if you run into issues.

Spoiler:

I originally posted several of these as standalone ASM hacks. I decided to bring them together by reimplementing them in C instead of having so many
bpre-trade-whatever
repositories on my Github. I have privated the repos containing the standalone ASM versions, and deleted the posts about them. Sorry for any confusion.

Super Versekr Dark February 9th, 2020 3:40 PM

Quote:

Originally Posted by ~Andrea (Post 10104413)
Colored Stats based on Nature[RUBY]
https://i.imgur.com/sNVysl4.png
To implement this feature, only one routine is needed:
Spoiler:

Code:

.THUMB
.ALIGN 2

PUSH {R0-R7}
LDR R1, = 0x02018009
LDRB R1, [R1]
MOV R0, #0x64
MUL R1, R0
LDR R0, = 0x03004360
ADD R0, R0, R1
PUSH {R1-R7}
BL GET_NATURE
POP {R1-R7}
LDR R1, = 0x081FD070
MOV R2, #5
MUL R0, R2
ADD R5, R0, R1

MOV R4, #1
LOOP:
LDR R1, = 0x2018009
LDRB R1, [R1]
MOV R0, #0x64
MUL R0, R1
LDR R1, = 0x03004360
ADD R0, R0, R1

MOV R2, PC
ADD R2, R2, #0x74
LDRB R1, [R2, R4]
MOV R7, R1

GET_DATA:
PUSH {R1-R7}
BL GET_MON_DATA
POP {R1-R7}
MOV R1, R0
LDR R0, .BUFFER
PUSH {R0-R7}
BL INT_TO_DEC
POP {R0-R7}

MOV R0, R4
MOV R1, #3
PUSH {R1-R7}
BL MOD
POP {R1-R7}
LSL R3, R0, #1
ADD R3, R3, #7

LDR R0, .BUFFER
MOV R1, #0xF

MOV R2, #22
CMP R4, #3
BLT COLORED

ADD R2, R2, #9

COLORED:
SUB R7, R7, #0x3B
LDRB R7, [R5, R7]

CMP R7, #0
BEQ PRINT_STR
CMP R7, #0xFF
BEQ LOWER

UPPER:
MOV R1, #0xB
B PRINT_STR

LOWER:
MOV R1, #0xC

PRINT_STR:
PUSH {R0-R7}
MOV R4, #36
BL PRINT
POP {R0-R7}
ADD R4, R4, #1
CMP R4, #6
BNE LOOP
POP {R0-R7}

LDR R0, = 0x080A0048+1
BX R0

GET_NATURE:
LDR R1, = 0x0803F464+1
BX R1

PRINT:
LDR R4, = 0x080A1F48+1
BX R4

GET_MON_DATA:
LDR R2, = 0x0803CB60+1
BX R2

INT_TO_DEC:
LDR R2, = 0x08006DDC+1
BX R2

MOD:
LDR R2, = 0x081E0F08+1
BX R2

.ALIGN 2
.BUFFER:        .WORD        0x020231CC
.TABLE:                .BYTE        0x3A
                .BYTE        0x3B
                .BYTE        0x3C
                .BYTE        0x3E
                .BYTE        0x3F
                .BYTE        0x3D
                .HWORD        0



After compiling the routine in a free offset, go to 0x09FFBC and overwrite the bytes with 00480047xxxxxx08.
Instead of the XX, will be entered the offset of previous routine + 1 and in Little Endian format (example: 08123456 -> 57 34 12 08).

How to invert the colors from red to blue?

ShinypikachuX February 12th, 2020 3:23 AM

Is it possible to make gym leaders have Pokemon based on your average party level ?

Super Versekr Dark March 4th, 2020 5:27 PM

Quote:

Originally Posted by FBI (Post 8528761)
Thanks. Though I would like to point out, to use them all you really need to know is how to insert them and what they do. I've documented a guide on how to insert for beginners (it's a link in the FAQ first post). If you don't understand something or don't see how some routine works, feel free to ask!


:3



I'm still not understanding the incentive to randomizing the starting Pokemon. I suppose it would be a small bit of "game change" if someone were to play your hack more than once, but the feature seems a little useless to me :/



Yeah it definitely could, and should read off of a table. I'll have to redo that little bit :x


Battle Modes addon: Delete fainted Pokemon



For those hackers who like minigames, this routine will delete Pokemon who have fainted in battle. There's a few things that need to happen for this effect to occur.

1) Pokemon who die in battle must be deleted
2) Eggs are spared
3) Pokemon who die outside of battle must be deleted (Poison or another similar effect)

However, if you put this in turn basis, you will NEED to make another routine to delete the Player's party if he/she loses the match. This is because the turn counter isn't reached on the last turn the player loses :x

If you're lazy like me you can just put this routine in as a battle by move addon and cover the whiteout case. Which is actually fine. It's rather fast, because it deletes the Pokemon as they die, so the worse case scenario is unforeseeable. And if a Pokemon dies it will only need to loop 5 times only doing operations on one of the 5 loops. If you're curious looping a maximum of 21 times is the worst case scenario (all 6 of your Pokemon die in 1 turn i.e never, and even if that did happen it'd be done in less .25 seconds). So it's fine to put in the battle by move section without expecting the game to lag.


How to insert:
Insert as addon to battle modes battle by move.
You will notice that near the start of the routine there is some commented out code (denoted by a prefix "@" symbol). That's for a flag check. Change [flag/4] = your flag/4 in hex if you want to toggle by flag. Of course the normal battle mode toggle flag should be used as well.

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r5, lr}
        @mov r0, #0x[flag/4]
        @lsl r0, r0, #0x2
        @ldr r3, =(0x806E6D0 +1)
        @bl linker
        @cmp r0, #0x0
        @beq end
        ldr r0, =(0x2023E8A)
        ldrb r0, [r0]
        cmp r0, #0x0
        beq realEnd
        mov r5, #0x0

loop:
        ldr r0, =(0x2024029)
        ldrb r4, [r0]
        cmp r5, r4
        beq end
        ldr r0, =(0x2024284)
        mov r1, #0x64
        mul r1, r1, r5 @slot
        add r0, r0, r1 @address
        mov r1, #0x39 @C_HP
        ldr r3, =(0x803FBE8 +1)
        bl linker
        cmp r0, #0x0
        beq adjustSlots

skip:
        add r5, r5, #0x1
        b loop

adjustSlots:
        cmp r5, #0x5
        bge writeLastZero
        mov r2, #0x5
        sub r2, r2, r5
        mov r0, #0x64
        mul r2, r2, r0 @size
        mov r1, r5
        mul r1, r1, r0
        ldr r0, =(0x2024284)
        add r0, r0, r1 @dest
        mov r1, #0x64
        add r1, r0, r1 @src
        ldr r3, =(0x8040B08 +1)
        bl linker

writeLastZero:
        ldr r0, =(0x2024478)
        mov r1, #0x0
        mov r2, #0x64
        ldr r3, =(0x81E5ED8 +1)
        bl linker

correctCounters:
        ldr r0, =(0x2024029)
        ldrb r1, [r0]
        sub r1, r1, #0x1
        strb r1, [r0]
next:
        mov r5, #0x0
        b loop       

end:
        ldr r0, =(0x2024029)
        ldrb r0, [r0]
        cmp r0, #0x0
        bne realEnd
        mov r0, #0x5E
        lsl r0, r0, #0x4
        ldr r3, =(0x806E6A8 +1)
        bl linker
        b realEnd

linker:
        bx r3

realEnd:
        pop {r0-r5, pc}

.align 2





Usage:
If you opted to use a flag, set it to allow further battles to delete Pokemon as they faint. If you didn't just sit back and let the unicorns inside the game do the rest.


I need help for pokemon ruby routine:

Spoiler:
.text
.align 2
.thumb
.thumb_func

main:
push {r0-r5, lr}
@mov r0, #0x94
@lsl r0, r0, #0x2
@ldr r3, =(0x8069340 +1)
@bl linker
@cmp r0, #0x0
@beq end
ldr r0, =(0x202252E)
ldrb r0, [r0]
cmp r0, #0x0
beq realEnd
mov r5, #0x0

loop:
ldr r0, =(0x20226D1)
ldrb r4, [r0]
cmp r5, r4
beq end
ldr r0, =(0x2022928)
mov r1, #0x64
mul r1, r1, r5 @slot
add r0, r0, r1 @address
mov r1, #0x39 @C_HP
ldr r3, =(0x803cb60 +1)
bl linker
cmp r0, #0x0
beq adjustSlots

skip:
add r5, r5, #0x1
b loop


adjustSlots:
cmp r5, #0x5
bge writeLastZero
mov r2, #0x5
sub r2, r2, r5
mov r0, #0x64
mul r2, r2, r0 @size
mov r1, r5
mul r1, r1, r0
ldr r0, =(0x2022928)
add r0, r0, r1 @dest
mov r1, #0x64
add r1, r0, r1 @src
ldr r3, =(0x803D910 +1)
bl linker


writeLastZero:
ldr r0, =(0x2022B24)
mov r1, #0x0
mov r2, #0x64
ldr r3, =(0x81E275C +1)
bl linker

correctCounters:
ldr r0, =(0x20226D1)
ldrb r1, [r0]
sub r1, r1, #0x1
strb r1, [r0]
next:
mov r5, #0x0
b loop

end:
ldr r0, =(0x20226D1)
ldrb r0, [r0]
cmp r0, #0x0
bne realEnd
mov r0, #0x5E
lsl r0, r0, #0x4
ldr r3, =(0x8069318 +1)
bl linker
b realEnd


linker:
bx r3

realEnd:
pop {r0-r5, pc}


.align 2

dearman4 March 11th, 2020 4:52 PM

Quote:

Originally Posted by FBI (Post 8547363)

Temporarily disabling EXP gains from battle



It was brought to my attention by some requesters that for their battle/tournament events they wouldn't want their Pokemon leveling up. This routine disables the exp gains in battle. Note that the player can still use stuff like Rare Candy to level. The fix to that is exactly the same as this, but with slight modifications. I hope you don't give the player a chance to rare candy in battle though or I will go to your hack's thread and severly criticize your lack of common sense :c


How to insert:

Compile and insert the following routine into free space:

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
        push {r0-r3}
        mov r0, #0xFF
        lsl r0, r0, #0x1
        add r0, r0, #0x4
        ldr r2, =(0x806E6D0 +1) @checkflag 0xFF *0x2 + 4 = 0x202
        bl linker
        cmp r0, #0x1
        beq skip
        pop {r0-r3}
        cmp r0, #0x64
        beq noCrash
        ldr r0, =(0x8021D24 +1)
        bx r0

skip:
        pop {r0-r3}

noCrash:
        ldr r1, [r5]
        add r1, #0x53
        ldrb r0, [r1]
        ldr r2, =(0x8021D04 +1)

linker:
        bx r2

.align 2


Here's a compiled version:
Code:

0F B4 FF 20 40 00 04 30 07 4A 00 F0 0C F8 01 28 04 D0 0F BC 64 28 02 D0 04 48 00 47 0F BC 29 68 53 31 08 78 02 4A 10 47 D1 E6 06 08 25 1D 02 08 05 1D 02 08




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

00 00 00 49 08 47 XX XX XX 08


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

Usage:

If flag 0x202 is set, the EXP gains will be disabled. Obviously, to re-enable just clear the flag.
Currently the way I'm doing this is by making the game act like the player's party is already max level, so therefore they don't gain exp :)

Is there a way to do this in Emerald? Also, is there a way to have a flag reduce experience gain by half in Emerald? I've implemented the gen VI exp share asm but that gives 100% to every pokemon, I would really like to have the amount be configurable!

AkameTheBulbasaur March 27th, 2020 1:41 AM

Shiny ShowPokePic (For FireRed)

If you use these two routines, then if you set Var 0x8003 to 0x1, before using the showpokepic command in an NPC script, then the Pokemon in the resulting picture will appear Shiny!

Spoiler:
/* Put 00 49 08 47 XX XX XX 08 at 0x8398C */
.text
.align 2
.thumb
.thumb_func
.global ShinyPalette

CheckVar:
ldr r1, .Var8003
ldrh r1, [r1]
cmp r1, #0x1
beq Shiny

Normal:
ldr r1, .NormalPal
lsl r4, r0, #0x3
add r4, r4, r1
ldrh r1, [r4, #0x4]
b Return

Shiny:
ldr r1, .ShinyPal
lsl r4, r0, #0x3
add r4, r4, r1
ldrh r1, [r4, #0x4]

Return:
str r1, [sp, #0xC]
mov r1, #0x0
ldr r2, .Return
bx r2

.align 2
.Var8003: .word 0x020370BE
.NormalPal: .word 0x0823730C
.ShinyPal: .word 0x082380CC
.Return: .word 0x08083999


Spoiler:
/* Put 00 49 08 47 XX XX XX 08 0x44198 */
.text
.align 2
.thumb
.thumb_func
.global ShinyPalette

CheckVar:
ldr r1, .Var8003
ldrh r1, [r1]
cmp r1, #0x1
beq Shiny

Normal:
cmp r0, #0x7
bls Shiny
lsl r0, r4, #0x3
ldr r1, .NormalPal
b Return

Shiny:
lsl r0, r4, #0x3
ldr r1, .ShinyPal

Return:
ldr r4, .Return
bx r4

.align 2
.Var8003: .word 0x020370BE
.NormalPal: .word 0x0823730C
.ShinyPal: .word 0x082380CC
.Return: .word 0x080441AD


https://i.imgur.com/e8dsgRM.pnghttps://i.imgur.com/KRqGbo2.png

(First picture is with 0x8003 = 0x1, second is without).

ScizorBlade April 13th, 2020 10:57 AM

Quote:

Originally Posted by Pokemon_XY (Post 9010564)

Time Box triggered along with the Start Menu


Preview: (Click to see the GIF animation)
Attachment 77173
The routines are only for FR. I haven't found any bugs in it. However, the CPU will run much more instructions so that it will be a bit (really?) slower when you open the 'pokemon', 'bag'..... menus.
1) Insert the RTC routine via the tool 'DNS'.
2) Insert these routines and do the byte changes:
Routine I:
Spoiler:
byte changes:
Code:

0x6F09C - 00 48 00 47 XX+1 XX XX 08
change all the 0x8750000 in the routine to the insert offset of the routine.
change all the 0x8750001 in the routine to the insert offset + 1 of the routine.


routine:
Code:

.thumb
bl box_func
ldr r1, =0x20370FF
ldrb r0, [r1]
add r0, #1
strb r0, [r1]
mov r0, #0
add sp, sp, #0xC
pop {r4, pc}
.ltorg

box_func:
push {r4, lr}
ldr r4, =0x2037101
ldr r0, =(0x8750000 + rbox_config)
ldr r3, =0x8003ce5
bl call_r3
strb r0, [r4]
ldr r3, =0x8003fa1
bl call_r3
ldrb r0, [r4]
mov r1, #0
ldr r3, =0x80F6F1D
bl call_r3
bl print_string
ldr r0, =(0x8750001 + print_string)
mov r1, #2
ldr r3, =0x807741D
bl call_r3
ldr r1, =0x20370C0
strh r0, [r1]
pop {r4, pc}
.ltorg

print_string:
push {r4-r7, lr}
sub sp, sp, #0xC
ldr r0, =0x2021cd0
add r7, r0, #0
ldr r1, =0x300553c
ldrb r5, [r1, #7] @minute
ldrb r6, [r1, #8] @second
ldrb r1, [r1, #6] @hour
mov r2, #1
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
bl go_padding
ldr r0, =0x2021CF0
add r7, r0, #0
add r1, r5, #0
mov r2, #1
mov r3, #2
ldr r4, =0x8008e79
bl call_r4
bl go_padding
ldr r0, =0x2021d04
add r7, r0, #0
add r1, r6, #0
mov r2, #1
mov r3, #2
ldr r4, =0x8008e79
bl call_r4
bl go_padding
ldr r5, =0x2021D18
ldr r1, =(0x8750000 + string)
add r0, r5, #0
ldr r3, =0x8008FCD
bl call_r3
ldr r0, =0x2037101
ldrb r0, [r0]
mov r1, #3
str r1, [sp]
mov r1, #0xff
str r1, [sp, #4]
mov r1, #0
str r1, [sp, #8]
mov r1, #2
add r2, r5, #0
mov r3, #4
ldr r4, =0x8002C49
bl call_r4
ldr r0, =0x2037101
ldrb r0, [r0]
mov r1, #2
ldr r3, =0x8003F21
bl call_r3
add sp, sp, #0xC
pop {r4-r7, pc}
.ltorg

go_padding:
push {lr}
ldrb r0, [r7]
cmp r0, #0
bne back
mov r0, #0xa1
strb r0, [r7]
back:
pop {pc}

call_r3:
bx r3

call_r4:
bx r4

.align 2
rbox_config:
.byte 0x0 @bg_id
.byte 0x1 @x
.byte 0x1 @y
.byte 0xa @width
.byte 0x2 @height
.byte 0xf
.hword 0x8 @tileset_ofs
.word 0x8419f76 @pixels

.align 2
string:
.byte 0xce, 0xdd, 0xe1, 0xd9, 0xf0, 0xfd, 0x2, 0xf0, 0xfd, 0x3, 0xf0, 0xfd, 0x4, 0xff



Routine II:
Spoiler:
byte changes:
Code:

0x6EF1E - 00 00 00 49 08 47 YY+1 YY YY 08


routine:
Code:

.thumb
cmp r0, #1
beq safari
ldr r0, =0x20370C0
ldrh r0, [r0]
ldr r3, =0x8077509
bl call_r3

safari:
ldr r4, =0x02037101
ldrb r0, [r4]
mov r1, #0
ldr r3, =0x806ef29

call_r3:
bx r3



Routine III:
Spoiler:
byte changes:
Code:

0x6f4e8 - 00 48 00 47 ZZ+1 ZZ ZZ 08


routine:
Code:

.thumb
push {lr}
ldr r0, =0x20370c0
ldrh r0, [r0]
ldr r3, =0x8077509
bl call_r3
ldr r1, =0x20370F0
ldr r0, =0x806f5a5
str r0, [r1]
mov r0, #0
pop {pc}
call_r3:
bx r3



In the byte change there are some XX XX XX, YY YY YY and ZZ ZZ ZZ. What are those?

furlan92 April 15th, 2020 4:25 AM

Quote:

Originally Posted by RuFF (Post 9660658)

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.



Did anyone ever make a fix for this? I'm trying to use it now and I can't control the level of the Pokemon.

EDIT: It works if you change the Pokemon data location.

Pyxal April 28th, 2020 7:22 AM

Greetings, everybody.

Question:
Has anybody got the Rival Naming Routine by Jambo51?
I believe the post [link] has died. Any help would be appreciated, and I under stand if Jambo has prohibited from spreading it.
This isn't a request, but a favour.


Cheers.

Pekin May 13th, 2020 5:45 AM

Hey all, I have a question that I was hoping someone here could help me out with. Spherical Ice was kind enough to send me some scripts and routines for me to edit to implement the "Madam Celadon" NPC feature from the Let's Go games into my Fakemon FireRed hack - you know, an NPC you talk to which predicts the nature for future encounters, at least for a set amount of time - or, steps. The first two scripts and the first asm routine I don't have any trouble editing and inserting, but the second asm routine gives me some error messages that I don't really know how to tackle. I hope it's cool if I post everything here.

The "Mrs. Nature" script is inserted at 3B1B44
The "Nature manipulation" routine is inserted at 34F050
The "Wore off" script is inserted at 3ADDD4
And the "Pedometer" routine is supposed to be inserted at 3ADE14, but I can't convert it to a .bin file without getting these error messages:
Code:

pedometer.asm:30: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:39: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:51: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:58: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:61: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:28: Error: invalid offset, value too big (0xFFFFFFFC)


I'm wondering if there's a different way I'm supposed to convert these, though, the only way I know is to put the .asm file in the same folder as thumb.bat, then navigate there with command prompt and type in "thumb routine.asm routine.bin" or something like that. I've noticed that this gives me some ridiculously long files with these routines - I can tell that it's because the new routine is generated at the specified offset, and the new pointer is included and everything, I'm just wondering if I'm supposed to be doing something different.

Anyway, here's what I got from Spherical Ice, all credit goes to him. I hope it's okay to post this here, he was a little too busy himself. Everything is pretty much the way I've inserted it - I'll edit the dialogue later, but other than that, the offsets and everything should match the way I've been inserting these.

Spoiler:
"Mrs. Nature" XSE script:
Spoiler:
Code:

#dynamic 0x3B1B44

#define VAR_FLOWER_TO_WATER 0x40A9
#define VAR_FLOWER_TO_THIN 0x40AB
#define VAR_NATURE 0x40B0
#define VAR_FORTUNE_PEDOMETER 0x40B1

#org @start
lock
textcolor 0x1
msgbox @string1 MSG_KEEPOPEN
showmoney 0x0 0x0 0x0
msgbox @string2 MSG_YESNO
compare LASTRESULT 0x1
if 0x1 goto @snippet1
msgbox @string3 MSG_NORMAL
hidemoney 0x0 0x0
release
end

#org @snippet1
checkmoney 0x2710 0x0
compare LASTRESULT 0x1
if 0x5 goto @snippet2
hidemoney 0x0 0x0
msgbox @string4 MSG_KEEPOPEN
preparemsg @string5
multichoice 0x0 0x0 0x1E 0x1
copyvar 0x8004 LASTRESULT
compare 0x8004 0x0
if 0x1 goto @snippet3
compare 0x8004 0x1
if 0x1 goto @snippet4
compare 0x8004 0x2
if 0x1 goto @snippet5
compare 0x8004 0x3
if 0x1 goto @snippet6
compare 0x8004 0x4
if 0x1 goto @snippet7
goto @snippet8

#org @snippet2
msgbox @string6 MSG_NORMAL
hidemoney 0x0 0x0
release
end

#org @snippet3
setvar VAR_FLOWER_TO_WATER 0x1
goto @snippet9

#org @snippet4
setvar VAR_FLOWER_TO_WATER 0x2
goto @snippet9

#org @snippet5
setvar VAR_FLOWER_TO_WATER 0x3
goto @snippet9

#org @snippet6
setvar VAR_FLOWER_TO_WATER 0x4
goto @snippet9

#org @snippet7
setvar VAR_FLOWER_TO_WATER 0x5
goto @snippet9

#org @snippet8
msgbox @string7 MSG_NORMAL
release
end

#org @snippet9
msgbox @string8 MSG_KEEPOPEN
preparemsg @string9
multichoice 0x0 0x0 0x1E 0x1
copyvar 0x8004 LASTRESULT
compare 0x8004 0x0
if 0x1 goto @snippet10
compare 0x8004 0x1
if 0x1 goto @snippet11
compare 0x8004 0x2
if 0x1 goto @snippet12
compare 0x8004 0x3
if 0x1 goto @snippet13
compare 0x8004 0x4
if 0x1 goto @snippet14
goto @snippet8

#org @snippet10
setvar VAR_FLOWER_TO_THIN 0x1
goto @snippet15

#org @snippet11
setvar VAR_FLOWER_TO_THIN 0x2
goto @snippet15

#org @snippet12
setvar VAR_FLOWER_TO_THIN 0x3
goto @snippet15

#org @snippet13
setvar VAR_FLOWER_TO_THIN 0x4
goto @snippet15

#org @snippet14
setvar VAR_FLOWER_TO_THIN 0x5
goto @snippet15

#org @snippet15
msgbox @string10 MSG_NORMAL
spriteface 0x1 0x2
pause 0x10
msgbox @string11 MSG_NORMAL
pause 0x10
spriteface 0x1 0x1
msgbox @string12 MSG_KEEPOPEN
sound 0x15
applymovement 0x1 @move1
waitmovement 0x0
checksound
call @snippet16
msgbox @string13 MSG_KEEPOPEN
pause 0x30
closeonkeypress
showmoney 0x0 0x0 0x0
msgbox @string14 MSG_KEEPOPEN
sound 0xF8
paymoney 0x2710 0x0
updatemoney 0x0 0x0 0x0
checksound
closeonkeypress
setvar VAR_FORTUNE_PEDOMETER 0x0
hidemoney 0x0 0x0
release
end

#org @snippet16
compare VAR_FLOWER_TO_WATER 0x1
if 0x1 goto @snippet17
compare VAR_FLOWER_TO_WATER 0x2
if 0x1 goto @snippet18
compare VAR_FLOWER_TO_WATER 0x3
if 0x1 goto @snippet19
compare VAR_FLOWER_TO_WATER 0x4
if 0x1 goto @snippet20
goto @snippet21

#org @snippet17
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet22
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet23
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet24
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet25
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet26
return

#org @snippet18
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet27
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet28
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet29
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet30
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet31
return

#org @snippet19
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet32
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet33
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet34
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet35
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet36
return

#org @snippet20
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet37
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet38
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet39
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet40
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet41
return

#org @snippet21
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet42
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet43
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet44
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet45
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet46
return

#org @snippet22
setvar VAR_NATURE 0x1
bufferstring 0x0 @string15
return

#org @snippet23
setvar VAR_NATURE 0x2
bufferstring 0x0 @string16
return

#org @snippet24
setvar VAR_NATURE 0x4
bufferstring 0x0 @string17
return

#org @snippet25
setvar VAR_NATURE 0x5
bufferstring 0x0 @string18
return

#org @snippet26
setvar VAR_NATURE 0x3
bufferstring 0x0 @string19
return

#org @snippet27
setvar VAR_NATURE 0x6
bufferstring 0x0 @string20
return

#org @snippet28
setvar VAR_NATURE 0x7
bufferstring 0x0 @string21
return

#org @snippet29
setvar VAR_NATURE 0x9
bufferstring 0x0 @string22
return

#org @snippet30
setvar VAR_NATURE 0xA
bufferstring 0x0 @string23
return

#org @snippet31
setvar VAR_NATURE 0x8
bufferstring 0x0 @string24
return

#org @snippet32
setvar VAR_NATURE 0x10
bufferstring 0x0 @string25
return

#org @snippet33
setvar VAR_NATURE 0x11
bufferstring 0x0 @string26
return

#org @snippet34
setvar VAR_NATURE 0x13
bufferstring 0x0 @string27
return

#org @snippet35
setvar VAR_NATURE 0x14
bufferstring 0x0 @string28
return

#org @snippet36
setvar VAR_NATURE 0x12
bufferstring 0x0 @string29
return

#org @snippet37
setvar VAR_NATURE 0x15
bufferstring 0x0 @string30
return

#org @snippet38
setvar VAR_NATURE 0x16
bufferstring 0x0 @string31
return

#org @snippet39
setvar VAR_NATURE 0x18
bufferstring 0x0 @string32
return

#org @snippet40
setvar VAR_NATURE 0x19
bufferstring 0x0 @string33
return

#org @snippet41
setvar VAR_NATURE 0x17
bufferstring 0x0 @string34
return

#org @snippet42
setvar VAR_NATURE 0xB
bufferstring 0x0 @string35
return

#org @snippet43
setvar VAR_NATURE 0xC
bufferstring 0x0 @string36
return

#org @snippet44
setvar VAR_NATURE 0xE
bufferstring 0x0 @string37
return

#org @snippet45
setvar VAR_NATURE 0xF
bufferstring 0x0 @string38
return

#org @snippet46
setvar VAR_NATURE 0xD
bufferstring 0x0 @string39
return

#org @string1
= Hmm[.]\p[.]\pAha!\nYes!\pShall I foresee the Nature of\nthose allies you have yet to meet?

#org @string2
= I'll charge you just [$]10,000.\nWouldn't you like to know?

#org @string3
= Hmm[.]\nYes, perhaps it's best[.]

#org @string4
= Well then, let me ask you a few\nquestions.

#org @string5
= [red_fr]There are five flowers before you.\nWhich do you water?

#org @string6
= You don't have enough money!\nSomething so powerful isn't free!

#org @string7
= Hm[.] Well, return when you change\nyour mind.

#org @string8
= Heh.\nI see, I see[.]

#org @string9
= [red_fr]Now, among the flowers I mentioned,\nwhich would you thin, if needed?

#org @string10
= Understood[.]\nNow I will look into your future.

#org @string11
= [.] [.] [.] [.]\n[.] [.] [.] [.]\p[.] [.] [.] [.]\n[.] [.] [.] [.]\p[.] [.] [.] [.]\n[.] [.] [.] [.]\pAha!

#org @string12
= Fate is guiding your path.\pThe encounters you will have are\nlikely to have[.]

#org @string13
= Yes!\nA[buffer1][red_fr] Nature!

#org @string14
= I will accept your payment now.\nThank you!

#org @string15
=  [green_fr]Hardy

#org @string16
=  [green_fr]Lonely

#org @string17
= n [green_fr]Adamant

#org @string18
=  [green_fr]Naughty

#org @string19
=  [green_fr]Brave

#org @string20
=  [green_fr]Bold

#org @string21
=  [green_fr]Docile

#org @string22
= n [green_fr]Impish

#org @string23
=  [green_fr]Lax

#org @string24
=  [green_fr]Relaxed

#org @string25
=  [green_fr]Modest

#org @string26
=  [green_fr]Mild

#org @string27
=  [green_fr]Bashful

#org @string28
=  [green_fr]Rash

#org @string29
=  [green_fr]Quiet

#org @string30
=  [green_fr]Calm

#org @string31
=  [green_fr]Gentle

#org @string32
=  [green_fr]Careful

#org @string33
=  [green_fr]Quirky

#org @string34
=  [green_fr]Sassy

#org @string35
=  [green_fr]Timid

#org @string36
=  [green_fr]Hasty

#org @string37
=  [green_fr]Jolly

#org @string38
=  [green_fr]Naive

#org @string39
=  [green_fr]Serious

#org @move1
#raw 0x62
#raw 0xFE




Nature manipulation ASM routine:
Spoiler:
Code:

.thumb

.equ free, 0x34F050
.equ VAR_NATURE, 0x40B0
.equ ABILITY_SYNCHRONIZE, 0x1C

.equ rom, 0x08000000

.org 0x3DDA4, 0xFF
    ldr r0, =(rom + main + 1)
    bx r0
.pool

.org free, 0xFF
main:
        ldr r0, [sp, #0x2C]
        lsl r0, r0, #0x18
        lsr r5, r0, #0x18
        lsl r1, r1, #0x10
        lsr r1, r1, #0x10
        mov r8, r1
        lsl r2, r2, #0x18
        lsr r7, r2, #0x18
        lsl r3, r3, #0x18
        lsr r6, r3, #0x18
fortune_check:
    push {r5}
    ldr r0, =(VAR_NATURE)
    bl var_load
    lsl r0, r0, #0x18
    lsr r5, r0, #0x18
fortune:
    cmp r5, #0
    beq skip_fortune
    cmp r5, #24
    bhi skip_fortune
    sub r0, r5, #1
    pop {r5}
    mov r5, r0
    b end
skip_fortune:
    pop {r5}
        bl rand
        lsl r0, r0, #0x18
        lsr r0, r0, #0x18
        cmp r0, #0
        bls end
synccheck:
        ldr r0, party_player
        mov r1, #0x2E
        mov r2, #0x0
        bl getattr
        mov r4, r0
        ldr r0, party_player
        mov r1, #0xB
        mov r2, #0x0
        bl getattr
        ldr r2, base_stats
        ldr r2, [r2]
        mov r1, #0x1C
        mul r0, r1
        add r2, r0, r2
        cmp r4, #0x0
        beq ability0
ability1:
        ldrb r1, [r2, #0x17]
        b checkability

ability0:
        ldrb r1, [r2, #0x16]
checkability:
        cmp r1, #ABILITY_SYNCHRONIZE
        bne end
copynature:
        ldr r0, party_player
        mov r1, #0x0
        mov r2, #0x0
        bl getattr
        bl getnature
        lsl r0, r0, #0x18
        lsr r5, r0, #0x18
end:
        ldr r0, return
        bx r0

rand:
        ldr r3, =(0x08044EC8|1)
        bx r3

getattr:
        ldr r3, =(0x0803FBE8|1)
        bx r3

getnature:
        ldr r3, =(0x08042EB4|1)
        bx r3

var_load:
        ldr r1, =(0x0806E568|1)
        bx r1

.align 2
.pool
        base_stats:        .word 0x080001BC
        return:        .word 0x0803DDB8|1
        party_player:        .word 0x02024284




"Fortune wore off" XSE script:
Spoiler:
Code:

#dynamic 0x3ADDD4

#org @start
msgbox @string1 MSG_SIGN
end

#org @string1
= It seems as if the fortune\nforetold has worn off[.]




Pedometer ASM routine: (This is the one that's giving me trouble, when I try to convert it to a .bin file)
Spoiler:
Code:

.thumb

.equ free, 0x3ADE14
.equ VAR_FORTUNE_PEDOMETER, 0x40B1
.equ STEPS_TO_RESET_PEDOMETER, 2999
.equ scr_fortune_wore_off, 0x3ADDD4
.equ rom, 0x08000000

.org 0x3DDA4, 0xFF
    ldr r0, =(rom + main + 1)
    bx r0
.pool

.org free, 0xFF
main:
    push {r4-r6,lr}
    bl fortune_teller_pedometer

end:
    pop {r4-r6}
    pop {r2}

call_via_r2:
    bx r2

fortune_teller_pedometer:
    push {lr}
    ldr r0, fortune_teller_nature
    ldr r2, =(0x0806E568|1)
    bl call_via_r2
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    cmp r0, #0
    beq fortune_teller_return
    ldr r4, =(VAR_FORTUNE_PEDOMETER)
    ldr r5, =(STEPS_TO_RESET_PEDOMETER)
    mov r0, r4
    ldr r2, =(0x0806E568|1)
    bl call_via_r2
    lsl r0, r0, #0x10
    lsr r1, r0, #0x10
    ldr r2, =(0x0806E584|1)
    cmp r1, r5
    bhi fortune_teller_pedometer_at_max

fortune_teller_increment:
    add r1, #1
    lsl r1, r1, #0x10
    lsr r1, r1, #0x10
    mov r0, r4
    bl call_via_r2
    b fortune_teller_return

fortune_teller_pedometer_at_max:
    ldr r0, =VAR_FORTUNE
    mov r1, #0
    ldr r2, =(0x0806E584|1)
    bl call_via_r2
    ldr r0, =(0x083ADDD4|1)
    ldr r2, =(0x08069AE4|1)
    bl call_via_r2

fortune_teller_return:
    pop {pc}

.pool



Team Embrace May 16th, 2020 9:26 AM

Hey everybody. First I would like to thank Andrea for successfully porting the physical/special split to Pokémon Ruby. Can someone take his ASM routine and update it to work with an expanded move table?
Spoiler:
.THUMB
.ALIGN 2

LDR R1, = 0x02024BE6
LDRH R1, [R1]

MOV R0, #0xC
MUL R1, R0
LDR R0, = 0x081FB12C
ADD R0, R0, R1

LDRB R0, [R0, #10]

CMP R0, #0
BEQ PHYSICAL

LDR R0, = 0x0803C132+1
BX R0

PHYSICAL:
LDR R0, = 0x0803BFC4+1
BX R0


In my modification the attack table starts at offset 0x900000. If more information is needed about my offsets I can provide that.

Super Versekr Dark May 16th, 2020 4:00 PM

Quote:

Originally Posted by Team Embrace (Post 10158794)
Hey everybody. First I would like to thank Andrea for successfully porting the physical/special split to Pokémon Ruby. Can someone take his ASM routine and update it to work with an expanded move table?
Spoiler:
.THUMB
.ALIGN 2

LDR R1, = 0x02024BE6
LDRH R1, [R1]

MOV R0, #0xC
MUL R1, R0
LDR R0, = 0x081FB12C
ADD R0, R0, R1

LDRB R0, [R0, #10]

CMP R0, #0
BEQ PHYSICAL

LDR R0, = 0x0803C132+1
BX R0

PHYSICAL:
LDR R0, = 0x0803BFC4+1
BX R0


In my modification the attack table starts at offset 9000. If more information is needed about my offsets I can provide that.

Change this for new table.

AttackData=1FB12C

Team Embrace May 17th, 2020 8:41 AM

Quote:

Change this for new table.
AttackData=1FB12C
Thanks for your reply Super Dark. I think my last post wasn't clear enough I am not talking about updating an editor's tool like PGE to support the expanded move table I've already done that. What I'm asking about is how to update Andrea's ASM routine to support the expanded move table in my ROM. Although I think were on the right track I wonder if change I posted below will work or do any other numbers need to be changed?
Spoiler:

.THUMB
.ALIGN 2

LDR R1, = 0x02024BE6
LDRH R1, [R1]

MOV R0, #0xC
MUL R1, R0
LDR R0, = 0x08900000
ADD R0, R0, R1

LDRB R0, [R0, #10]

CMP R0, #0
BEQ PHYSICAL

LDR R0, = 0x0803C132+1
BX R0

PHYSICAL:
LDR R0, = 0x0803BFC4+1
BX R0

Team Embrace May 19th, 2020 7:56 AM

Quote:

Originally Posted by PokeChu (Post 10152213)
Greetings, everybody.

Question:
Has anybody got the Rival Naming Routine by Jambo51?
I believe the post [link] has died. Any help would be appreciated, and I under stand if Jambo has prohibited from spreading it.
This isn't a request, but a favour.


Cheers.

Naming the Rival from the Overworld:
Spoiler:

The Code:

.text
.align 2
.thumb
.thumb_func
.global rivalnamingingame
main:
push {r0-r4,lr}
ldr r0, place
str r0, [sp, #0x4]
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
mov r0, #0x4
mov r2, #0x0
mov r3, #0x0
bl place2
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
ldrb r0, [r1, #0x0]
cmp r0, #0xFF
beq failsafe
cmp r0, #0x0
beq failsafe
return: pop {r0-r4}
pop {pc}
place2: ldr r4, actualroutine
bx r4
failsafe: ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
strb r2, [r1, #0x0]
cmp r2, #0xFF
beq return
add r0, #0x1
add r1, #0x1
b loop
.align
place: .word 0x080568E1
ramlocation: .word 0x03005008
standard: .word 0x00003A4C
actualroutine: .word 0x0809D955
rivalname: .word 0x08FFFFFF

Where to insert: Anywhere! This routine is called from a script in the game, and as such, doesn't need to be carefully linked into existing routines. All you need to do is remember the rule of THUMB, add 1 to the offset when calling it!

Explanation: It's what it says on the tin, it lets you name your rival from the in game overworld, allowing for Silver like naming, or indeed, any other possibility you can come up with. The rivalname: .word 0x08FFFFFF is for if the player leaves the name box blank. It will fill it with a standard name instead. This standard name is up to you to create. Simply compile a name with XSE, and point that pointer to it.

You also need to put this routine in the game, or else it won't be able to load past the intro without naming the rival. All it does is temporarily write a holding name to the rival buffer so that the game doesn't crash.

.text
.align 2
.thumb
.thumb_func
.global rivalnamingskip
main:
ldr r1, [r6, #0x0]
ldr r0, number
mov r8, r0
add r1, r8
push {r1}
ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
cmp r2, #0xFF
beq end
strb r2, [r1, #0x0]
add r0, #0x1
add r1, #0x1
b loop
end: strb r2, [r1, #0x0]
pop {r1}
mov r0, sp
ldr r3, return
bx r3
.align
number: .word 0x00003A4C
rivalname: .word 0x08FFFFFF
return: .word 0x08054A75

Where to insert: Navigate to 0x54A6A, and change the following bytes to this:
01 49 08 47 00 00 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: It simply writes a placeholder name into the [rival] buffer so the game doesn't crash. Obviously, you shouldn't be using the [rival] buffer until the player has named the rival, so it shouldn't be a problem.

To make this work, navigate to 0x103690, and change the pointer there to 0x1307D1.


OG post by tajaros

Pyxal May 19th, 2020 11:34 AM

Quote:

Originally Posted by Team Embrace (Post 10159943)
Naming the Rival from the Overworld:
Spoiler:

The Code:

.text
.align 2
.thumb
.thumb_func
.global rivalnamingingame
main:
push {r0-r4,lr}
ldr r0, place
str r0, [sp, #0x4]
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
mov r0, #0x4
mov r2, #0x0
mov r3, #0x0
bl place2
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
ldrb r0, [r1, #0x0]
cmp r0, #0xFF
beq failsafe
cmp r0, #0x0
beq failsafe
return: pop {r0-r4}
pop {pc}
place2: ldr r4, actualroutine
bx r4
failsafe: ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
strb r2, [r1, #0x0]
cmp r2, #0xFF
beq return
add r0, #0x1
add r1, #0x1
b loop
.align
place: .word 0x080568E1
ramlocation: .word 0x03005008
standard: .word 0x00003A4C
actualroutine: .word 0x0809D955
rivalname: .word 0x08FFFFFF

Where to insert: Anywhere! This routine is called from a script in the game, and as such, doesn't need to be carefully linked into existing routines. All you need to do is remember the rule of THUMB, add 1 to the offset when calling it!

Explanation: It's what it says on the tin, it lets you name your rival from the in game overworld, allowing for Silver like naming, or indeed, any other possibility you can come up with. The rivalname: .word 0x08FFFFFF is for if the player leaves the name box blank. It will fill it with a standard name instead. This standard name is up to you to create. Simply compile a name with XSE, and point that pointer to it.

You also need to put this routine in the game, or else it won't be able to load past the intro without naming the rival. All it does is temporarily write a holding name to the rival buffer so that the game doesn't crash.

.text
.align 2
.thumb
.thumb_func
.global rivalnamingskip
main:
ldr r1, [r6, #0x0]
ldr r0, number
mov r8, r0
add r1, r8
push {r1}
ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
cmp r2, #0xFF
beq end
strb r2, [r1, #0x0]
add r0, #0x1
add r1, #0x1
b loop
end: strb r2, [r1, #0x0]
pop {r1}
mov r0, sp
ldr r3, return
bx r3
.align
number: .word 0x00003A4C
rivalname: .word 0x08FFFFFF
return: .word 0x08054A75

Where to insert: Navigate to 0x54A6A, and change the following bytes to this:
01 49 08 47 00 00 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: It simply writes a placeholder name into the [rival] buffer so the game doesn't crash. Obviously, you shouldn't be using the [rival] buffer until the player has named the rival, so it shouldn't be a problem.

To make this work, navigate to 0x103690, and change the pointer there to 0x1307D1.


OG post by tajaros

I am so sorry! I had found this routine and forgot to mention it here. Terribly sorry.


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.