I don't know if anyone's been working on this lately, but I've been itching to share this.
FireRed lacks a system that uses a Region Dex order seperate from the National Dex. If you were to have a Region Dex and a National Dex, your National Dex would look unprofessional. What I'm putting here is my work towards a Region Dex system for FireRed. I would like to stress however that it is both unoptimized and unfinished, but I really wanted to release this.
The current routinesSpoiler:
Loading the right speciesSpoiler:
Insert 00 48 00 47 xx xx xx 08 at 0x10356CCode:.text .align 2 .thumb .thumb_func main: mov r4, r8 lsl r0, r4, #0x10 lsr r5, r0, #0x10 add r4, #0x1 ldr r0, .HoennDex lsl r5, r5, #0x1 add r0, r0, r5 ldrh r0, [r0] mov r5, r0 ldr r0, .return bx r0 .align 2 .HoennDex: .word 0x08252216 .nationaltoindex: .word 0x08043200+1 .return: .word 0x08103574+1
Correct numberingSpoiler:
Insert 00 4A 10 47 xx xx xx 08 at 0x104A60Code:.text .align 2 .thumb .thumb_func lsr r4, r4, #0x18 lsl r6, r6, #0x18 lsr r6, r6, #0x18 ldr r1, .indextonatdex bl Linker mov r2, r0 ldr r1, .dexarea add r1, r1, #0xa ldrb r1, [r1] cmp r1, #0x1 beq regionnumber mov r0, r2 b GoBack Linker: bx r1 GoBack: ldr r2, .return bx r2 regionnumber: mov r0, #0x0 ldr r1, .HoennDex Loop: mov r0, r3 lsl r3, r3, #0x1 add r1, r1, r3 ldrh r3, [r1] add r0, r0, #0x1 cmp r1, r2 bne Loop b GoBack .align 2 .HoennDex: .word 0x08252324 .indextonatdex: .word 0x08043298+1 .flagcheck: .word 0x0806e6d0+1 .return: .word 0x08104a6a+1
Fixing the end of the region dexSpoiler:
Insert 00 49 08 47 xx xx xx 08 at 0x1035F0Code:.text .align 2 .thumb .thumb_func main: push {r2} mov r2, #0x0 ldr r1, .HoennDex loop: lsl r0, r2, #0x1 add r0, r0, r1 ldrh r0, [r0] add r2, #0x1 cmp r0, r5 bne loop lastpart: ldr r1, =0x100 /*Put the length of your Region Dex here, this supports beyond 256*/ mov r10, r2 pop {r2} str r2, [r3, #4] mov r8, r9 mov r0, r8 cmp r0, r1 ble jump ldr r1, .return2 bx r1 jump: ldr r1, .return bx r1 .align 2 .HoennDex: .word 0x08252324 .return: .word 0x0810356c+1 .return2: .word 0x08103906+1
To-Do list
Fix counting the Region Dex for things like the start screen and talking to the Professor
Displaying the Region Dex number when you don't have the National Dex on the summary screen
Making searches and habitat lists use Region Dex numbers before the National Dex
Send me a PM if you're interested in fixing up what's left.
umThere is a ".dexarea" in Correct numbering routine that doesn't have any value. I tried inserting .dexarea .word 0x8a90000 at the bottom of the code but it doesn't work. Any idea?
Black Sludge Implementation:
-> Insert at x1BE18: 00 49 08 47 XX+1 XX XX 08 00 00
-> Routine at XXXXXX:
Spoiler:
ZZ is the index of mystery byte
KK is the index of magic guard (If you don't have magic guard remove the bolded part of ASM)
Code:.text .align 2 .thumb .thumb_func main: sub r0, r5, #0x1 cmp r0, #0x2A bls table cmp r5, #0xZZ beq bsludge b exit table: ldr r1, =0x0801BE23 bx r1 bsludge: mov r0, #0x58 mul r0, r7 mov r2, r8 add r1, r0, r2 add r1, #0x20 ldrb r3, [r1, #0x1] cmp r3, #0x3 beq healer ldrb r3, [r1, #0x2] cmp r3, #0x3 beq healer [B] ldrb r3, [r1, #0x0] cmp r3, #0xKK beq exit[/B] cmp r6, #0x0 bne exit add r1, r0, r2 ldr r3, =0x02023D50 ldrh r0, [r1, #0x2c] lsr r0, r0, #0x03 cmp r0, #0x0 bne nonZeroDamage mov r0, #0x1 nonZeroDamage: str r0, [r3, #0x0] ldr r0, DSPointer bl scriptManager mov r0, #0x4 str r0, [sp, #0xC] add r0, r7, #0x0 add r1, r5, #0x0 bl scriptDelayer b exit healer: ldr r1, =0x0801C09F bx r1 exit: ldr r2, =0x0801C953 bx r2 scriptManager: ldr r1, =0x0801BBE5 bx r1 scriptDelayer: ldr r2, =0x080C7209 bx r2 .align 2 DSPointer: .word 0x08GGGGGG
-> Battle Script at GGGGGG:
Spoiler:
Code:#org @start call @func end2 #org @func playanimation 0x1 0x1B 0x0 setword 0x203C020 0x08SSSSSS printstring 0x184 waitmessage 0x40 orword 0x2023DD0 0x100 graphicalhpupdate 0x1 datahpupdate 0x1 faintpokemon 0x1 0x0 0x0 return
String at SSSSSS:
Code:FD 0F 00 DD E7 00 DC E9 E6 E8 FE D6 ED 00 FD 16 AB FF
The animation of negative sludge can be improved by some expert in animation hacking.
(OPTIONAL) Update the Leftovers message to latest Generation (used for positive Black Sludge too):
-> At 1C0F4: HH HH HH 08 (In reverse hex)
-> Battle Script at HHHHHH:
Spoiler:
Code:#org @start call @func end2 #org @func playanimation 0x1 0x7 0x0 setword 0x203C020 0x08TTTTTT printstring 0x184 waitmessage 0x40 orword 0x2023DD0 0x100 graphicalhpupdate 0x1 datahpupdate 0x1 return
String at TTTTTT:
Code:FD 0F 00 E6 D9 E7 E8 E3 E6 D9 D8 FE D5 00 E0 DD E8 E8 E0 D9 00 C2 CA 00 E9 E7 DD E2 DB 00 DD E8 E7 00 FD 16 AB FF
Has anyone else tried this EV-Reducing Berries ?
I keep trying it but to no avail I just can't seem to get it to work.
I assemble the routine and place it at 0x7900B0, then edit the given script to;
XSEscript:
Code:#dynamic 0x740000 '----Main---- #org @start special 0x9F ///Choose Pokemon from Party & store it on var 0x8004 waitstate bufferpartypokemon 0x0 0x8004 setvar 0x800D 0x1A ///EV-stat 0x1A = HP setvar 0x8000 0xA ///EV-stat amount to subtract 0xA = 10 callasm 0x87900B1 ///EV-Reducing Berries ASM(pointer + 1) compare 0x800D 0xFF ///Compare last result to 255 if 0x1 goto @snippetFail buffernumber 0x1 0x800F msgbox @stringDecrese 0x6 removeitem 0x99 0x1 ///Item 0x99 = Pomeg Berry release end '--------------- #org @snippetFail msgbox @stringFail 0x6 release end '--------- ' Strings '--------- #org @stringDecrese = [buffer1] lost [buffer2]\nHP EVs! #org @stringFail = It would have no effect!
Is there something I'm doing wrong or is there a better way to do this?
I'm merely trying to recreate the Pomeg Berry from Emerald in Fire Red...
Not to mention EV-Reducing Berries are rather useful when EV training...
Also since I'm here I was wondering what gltiches from the first gen could be simulated with asm in Fire Red?
Would like to make a working MissingNo that will check the players name and base its form off of the characters in the certain spots like in Blue and Red. Would be cool to have the item duplication glitch as well but one step at a time...
The reason I ask is because I'm trying to make a Glitch/Error Version...
Keeping their sporadic nature but making them contained and fun to play with...
GlitchQuests are rather fun when they work and do some crazy stuffs>_< hahaha.
Anyway thanks for the time and any advice given...
I was wondering if it would be possible to update the Everstone to have its Gen Six breeding effect?
To review, the Gen Six Everstone:
•Has a 100% chance to pass down the nature of the parent holding it.
•If both parents are holding the Everstone, the Nature passed down will be randomly chosen from the two parents (if they both have the same nature this is unnoticeable.)
I was wondering if it would be possible to update the Everstone to have its Gen Six breeding effect?
To review, the Gen Six Everstone:
•Has a 100% chance to pass down the nature of the parent holding it.
•If both parents are holding the Everstone, the Nature passed down will be randomly chosen from the two parents (if they both have the same nature this is unnoticeable.)
I believe FBI has code for that somewhere? Though that might just be for Fire Red. Should be easy enough to port.
Wow, you took that well. I was expecting you to be a little annoyed at me for practically butchering through most of your suggestions. I like people who understand. Here's something you'll enjoy :)
Introducing ASM to your Bank scripts
Bank scripts are normally very simple. There's a variable which holds the amount of money you have, normally holding $65, 535. Or if the scripter who wrote the script is good like I am, it'd become 999, 999, 999. Anyways, bragging aside, I made two routines to help improve your banking experience :P
Adding Interest into your variable
Before you can insert this, you need to have the Minute Routines Framework inserted.
This is very specific to the bank variable you're using. I'll show you the routine first. There's some orange text for you to look at again. The first orange text is how often to add interest, 0x1 is every minute and 0x3b would be every hour. The second orange text is the amount you need to subtract from 0x4100 to reach your variable. Note, you bank variable should be in the range of 0x4011 - 0x40FF. If it's not you're using an unsafe variable and should change it to something.
After you've fixed the orange text to match your bank script compile and insert into free space.
Spoiler:
Code:.text .align 2 .thumb .thumb_func main: push {r0-r5, lr} ldr r0, =(0x300500C) ldr r0, [r0] add r0, r0, #0x10 ldrb r0, [r0] @mins [COLOR="DarkOrange"] mov r1, #0x1 @frequency (range is from 0x1 to 0x3B). 0x1 = every minute[/COLOR] ldr r2, =(0x81E4684 +1) bl linker2 cmp r0, #0x0 beq end calculateInterest: mov r0, #0x82 @ r0 = var = 0x82 lsl r0, #0x7 @ var = 0x82 * 0x80 = 4100 [COLOR="DarkOrange"] sub r0, r0, #0x1 @4100 -1 = 0x40FF. Subtract a sufficient amount to reach your var @ the above is the variable tracking bank deposit value. Change amount subtracted if your var is different[/COLOR] mov r5, r0 ldr r4, =(0x806E568 +1) @get var bl linker mov r1, #0xA @0xA = 10% mov r4, r0 mul r0, r0, r1 @multiply (percent * 100) * (Original price) mov r1, #0x64 ldr r2, =(0x81E4018 +1) @integer divide by 100 = rounded price bl linker2 add r1, r0, r4 @finalized total mov r0, r5 ldr r4, =(0x806E584 +1) @set var bl linker end: pop {r0-r5, pc} linker: bx r4 linker2: bx r2 .align 2
After you've inserted this routine, append a pointer to it to the Minute Routine Framework table.
Usage:
No usage. Interest is added on a minute basis to your variable of choice (which should be deposited value).
Battle Money Straight into a variable
So this one is kind of specific, but I kinda felt like helping someone out so I did it. All it does is, intercept the money being given to the bag, and adds it to a given variable instead. It's toggled by flag 0x250.
How to insert:
Look at the orange text. Similar to the first routine, you will need to change the amount subtracted to match your variable (remember you're subtracting two hex numbers). Once you've fixed it, you can go ahead and compile the routine into free space (write down the place you compiled it to).
Spoiler:
Code:.text .align 2 .thumb .thumb_func @hook at 080259F0 @00 49 08 47 01 00 83 08 main: mov r1, #0xA4 lsl r1, r1, #0x2 add r0, r0, r1 mov r1, r4 ldr r4, =(0x20370B8) strh r1, [r4] push {r0-r4} flagCheck: [COLOR="DarkOrange"]mov r0, #0x94 lsl r0, r0, #0x2 ldr r2, =(0x806E6D0 +1) @checkflag 0x94 *0x4 = 0x250[/COLOR] bl linker cmp r0, #0x0 beq endTwo moveToBankVar: mov r0, #0x82 @ r0 = var = 0x82 lsl r0, #0x7 @ var = 0x82 * 0x80 = 4100 [COLOR="DarkOrange"] sub r0, r0, #0x1 @4100 -1 = 0x40FF, this is the variable tracking bank deposit value. Change amount subtracted if your var is different[/COLOR] mov r4, r0 ldr r2, =(0x806E568 +1) @get var bl linker ldr r1, =(0x20370B8) ldrh r1, [r1] add r1, r1, r0 mov r0, r4 ldr r2, =(0x806E584 +1) @set var bl linker end: pop {r0-r4} mov r4, r1 ldr r1, =(0x8025A00 +1) bx r1 endTwo: pop {r0-r4} mov r4, r1 push {r4} ldr r4, =(0x809FDA0 +1) bl linker2 pop {r4} ldr r1, =(0x8025A00 +1) bx r1 linker2: bx r4 linker: bx r2 .align 2
Now navigate to 0x259EC and insert the following byte changes:
Where XX XX XX is the reverse hex pointer to where you inserted this routine +1.Code:00 49 08 47 XX XX XX 08
Usage:
Flag 0x250 must be set for the routine to be toggled on, else money will be put in the player's bag as normal.
Hello. Glad I'd implemented it on my hack there are two problems and one question though.
My problem is upon defeating a trainer, the money that is supposed to be decreased by 10% is decreased by 100%. Upon setting flag 250, the every money that I get from a training is sent directly to the Var I had specified on the routine, and the playtime in trainer card stops at 00:59.
And one question, how to deposit the saved money?
Hello. As I'm aware, reading through the second routine, it basically stores all the money that would go to the player into the bank var instead, if a flag is set. To change the functionality there, you will have to edit the routine a little bit.
The first routine seems to just increment a variable based on the play time. It requires some other playtime fetching routine be installed already, make sure you've got all of that set up. If you have further problems feel free to ask in the ASM help thread.
the only problem left to me is the time stops upong setting flag and I don't know how to deposit the saved money. Anyway thanks for the reply.
All the codes are now on github and the auto-insertion is completed via armips.
https://github.com/jiangzhengwenjz/Double_wild_battle
Old post:
Spoiler:I'm here again and here's some information about double wild battle in BPRE. The system is not yet perfect, but I don't have time to improve it so I decided to release the code. Please credit Jambo51 because some of the codes are ripped from his FR649. However, iirr, Karatekid552 has released the ASM codes in FR649 on github, so I think it's not inappropriate to post them here. These routines will make it possible to have "double wild battle" in "grass battles".
Bugs fixed:
1. Loading only 1 pokemon
2. Capture animation
3. Audio error
4. Captured pokemon data
5. pokedex things
6. can't flee
7. nickname issues
Wild Double Battle in BPRE
Now the main bugs are all fixed and here's a picture of what we can do now. (I don't use an English ROM, sorry.)
![]()
The byte changes are in the comments of the routines, so please read carefully.
Spoiler:Code:.thumb /*0x82a26 - 04 49 08 47 0x82a38 - XX+1 XX XX 08 0x7F760 - 00 00*/ str r0, [sp] ldr r0, .opponent_slot add r1, r4, #0 add r2, r6, #0 mov r3, #0x20 ldr r4, .pokemon_make_3 bl linker_4 mov r1, #0 mov r2, #0 loop_1: mov r4, #0x64 ldr r0, .party_slot add r0, #0x56 mul r4, r1 add r0, r0, r4 ldrh r0, [r0] cmp r0, #0 bne add_1 increment: add r1, #1 cmp r1, #6 bne loop_1 cmp r2, #2 blt back_1 ldr r1, .offset ldr r2, .save_block_1 ldr r2, [r2] ldrb r3, [r2, #4] @bank lsl r3, r3, #2 add r1, r1, r3 ldr r1, [r1] ldrb r3, [r2, #5] @map lsl r3, r3, #2 add r1, r1, r3 ldr r1, [r1] ldr r1, [r1] ldr r3, [r1, #0x10] ldr r2, .tileset_table cmp r3, r2 bne back_1 bl get_block_id mov r2, #0 loop_2: mov r1, pc add r1, #0x92 lsl r3, r2, #2 add r1, r1, r3 ldrh r3, [r1] cmp r0, r3 beq calculation ldr r1, .end cmp r1, r3 beq back_1 add r2, #1 b loop_2 add_1: add r2, #1 b increment back_1: mov r0, #0 ldr r1, .battle_flag str r0, [r1] back_2: add sp, sp, #0x10 pop {r4-r6, pc} get_block_id: push {lr} ldr r0, .npc_state ldrh r1, [r0, #0x12] @Y ldrh r0, [r0, #0x10] @X ldr r4, .getter bl linker_4 pop {pc} calculation: ldrb r4, [r1, #2] cmp r4, #0x63 bhi doubletwo bl random mov r1, #0x64 bl mod_func doublethree: add r1, r4, #0 cmp r0, r1 bge back_1 double: mov r0, #1 ldr r1, .battle_flag str r0, [r1] ldr r4, .rand_grass bl linker_4 ldr r1, [r7, #4] lsl r0, r0, #2 add r0, r0, r1 ldrh r4, [r0, #2] ldr r1, .generate bl linker_1 add r6, r0, #0 bl random mov r1, #0x19 bl mod_func str r0, [sp] ldr r0, .opponent_slot add r0, #0x64 add r1, r4, #0 add r2, r6, #0 mov r3, #0x20 ldr r4, .pokemon_make_3 bl linker_4 b back_2 doubletwo: mov r0, #0 b doublethree mod_func: ldr r3, .mod_addr bx r3 random: ldr r2, .rand bx r2 linker_1: bx r1 linker_4: bx r4 .word 0x0005000A .word 0x0005000B .word 0x0005000C .word 0x0005000D .hword 0xFEFE .align 2 .opponent_slot: .word 0x0202402C .pokemon_make_3: .word 0x0803DD99 .party_slot: .word 0x02024284 .battle_flag: .word 0x02022B4C .offset: .word 0x083526A8 .save_block_1: .word 0x03005008 .tileset_table: .word 0x082D4A94 .npc_state: .word 0x02036E38 .getter: .word 0x08058E49 .end: .word 0x0000FEFE .mod_addr: .word 0x081E4685 .rand: .word 0x08044EC9 .rand_grass: .word 0x0808274D .generate: .word 0x080828F9
Code:.thumb .align 2 /*0x16824 - 00 48 00 47 JJ+1 JJ JJ 08*/ cmp r3, #5 beq .L_1 mov r0, #1 and r3, r0 cmp r3, #0 bne .L_0 .L_1: ldr r0, =0x801682D bx r0 .L_0: ldr r0, =0x801682D add r0, #0x42 bx r0
Please change [text offset] to a piece of text data. The text should be like "There're 2 pokemon on the opponent side and i can't lock on the target".Code:.thumb /*Change all 1D 1E 0A 08 to the pointer (+1) to this routine, and please do the change before inserting the routine!!!!!!!!!!!!!!!!!!*/ ldr r1, .battle_flag ldr r1, [r1] cmp r1, #5 bne normal ldr r1, .struct mov r2, #0x58 lsl r2, r2, #1 add r2, r1, r2 ldrh r1, [r1, #0x28] ldrh r2, [r2, #0x28] mul r1, r2 cmp r1, #0 bne two_mon normal: ldr r1, .pokeball bx r1 two_mon: push {r4, lr} mov r0, #0 mov r1, #2 ldr r2, .string_shown ldr r3, .bag_print ldr r4, .texter bl jump pop {r4, pc} jump: bx r4 .align 2 .battle_flag: .word 0x2022B4C .pokeball: .word 0x80A1E1D .struct: .word 0x2023C3C .bag_print: .word 0x810a1f9 .texter: .word 0x08108E71 .string_shown: .word 0x08[text offset]
Code:.thumb .align 2 /*21d46 - 00 47 21d94 - ZZ+1 ZZ ZZ 08*/ ldr r0, =0x2022b4c ldr r0, [r0] cmp r0, #5 beq double audio: ldr r0, =0x137 ldr r1, =0x80722A1 bl jump ldr r1, =0x8021D4B jump: bx r1 double: ldr r0, =0x2023C3C mov r1, #0x58 lsl r1, r1, #1 add r1, r0, r1 ldrh r0, [r0, #0x28] ldrh r1, [r1, #0x28] add r0, r0, r1 cmp r0, #0 beq audio ldr r1, =0x8021D4B add r1, #8 bx r1
Code:.thumb .align 2 /*0x2D44C - 30 47 0x2D480 - MM+1 MM MM 08 0x2D812 - 00 00 0x2D858 - 00 00 0x2D8A6 - 00 00 0x2D8F4 - 01 1C 0x2DF36 - 08 1C 0x2DE58 - 00 00 0x2DE84 - 00 00 0x2DEA4 - 00 00 0x2DEC2 - 04 1C 0x2D874 - 6C 3D 02 02 0x2D94C - 6C 3D 02 02 0x2DF64 - 6C 3D 02 02 0x2DF04 - 6C 3D 02 02*/ ldr r6, =0x2022b4c ldr r6, [r6] cmp r6, #5 bne normal ldr r6, =0x2023C3C ldrh r6, [r6, #0x28] cmp r6, #0 bne case_1 case_2: mov r0, #3 b back case_1: mov r0, #1 b back normal: mov r1, #1 eor r0, r1 back: ldr r6, =0x2023D6C ldr r1, =0x802d451 bx r1
Code:.thumb .align 2 /*0x2d95c - 00 48 00 47 NN+1 NN NN 08*/ push {r4, r5, lr} ldr r4, =0x0202402C ldr r0, =0x02023D6C ldrb r0, [r0] lsr r0, r0, #1 mov r1, #0x64 mul r0, r1 add r0, r0, r4 add r4, r0, #0 mov r1, #0xb ldr r2, =0x0802D965 bx r2
Code:.thumb .align 2 /*0x2d9de - 00 47 0x2da00 - UU+1 UU UU 08*/ ldr r0, =0x0202402C ldr r1, =0x02023D6C ldrb r1, [r1] lsr r1, r1, #1 mov r2, #0x64 mul r1, r2 add r0, r1, r0 mov r1, #0xb ldr r2, =0x0802D9E1 bx r2
Code:.thumb .align 2 /*0xEF5F8 - 10 47 0xEF680 - QQ+1 QQ QQ 08*/ ldr r2, =0x02037F1B ldr r0, =0x02022B4C ldr r0, [r0] cmp r0, #5 bne normal ldr r0, =0x02023C3C mov r1, #0x58 lsl r1, r1, #1 add r1, r0, r1 ldrh r1, [r1, #0x28] cmp r1, #0 beq normal mov r1, #3 strb r1, [r2] normal: mov r8, r2 ldr r0, =0x080EF5FB bx r0
After inserting the first routine, there will be a table in this format: 0A 00 05 00 0B 00 05 00 0C 00 05 00...... (The table is in the first routine and you can search for it)
The "05" is the rate of double battle in grass battles, which means 5% and you can change that on your own.
A, B, C, D are the ID of the 4 grass tile blocks and it's compatible with the clean BPRE 1.0 ROM.
As for now, there should still be some bugs like the fact that the name of captured pokemon is not shown right, but I won't do it now because I'm busy with my univ life. :)
I read your codes on github
And it says about 64 bit pc but what if one has 32 bit computer??
You can insert them manually, but it's really annoying and requires basic ASM knowledge
By basic asm do you mean compiling the asm codes and then writing the codes from .bin file to game pr writing asm codes???
Dunno if this will help you, but
Multiple Characters
Despite gender being binary in the games, there is actually an entire byte set aside for it in the second saveblock. You can change this byte with a simple ASM routine, e.g.
Spoiler:
Code:.align 2 .thumb @ Set gender from value in script var 0x8000 set_gender_byte: ldr r0, saveblock2_trainerdata ldr r0, [r0] ldr r1, variable ldrb r1, [r1] strb r1, [r0, #8] @ gender bx lr .align 2 saveblock2_trainerdata: .word 0x0300500C variable: .word 0x020370B8 @ script var 0x8000
Set it to zero for male and one for female. Use another byte for another for another character
Note, this will break the script checkgender command! In order to restore it, you should first call checkgender, copy the value it returns in 0x800D to another unused var. Then set the gender using the above. Then you can restore it properly.
Lastly, apply this hook (untested):
You'll need to customise that table at the bottom. Each character you want must have its own 6 byte entry, even if you don't plan on using all the frames. The example entry above is a duplicate male character. Just change the bytes to the overworld sprites of your new character (the same in advance map when chooses a sprite for an NPC). Keep in mind you'll need running frames for the target character.Spoiler:
Code:.align 2 .thumb @ 00 48 00 47 XX + 1 XX XX 08 at 0x05C7E8 (0805C7E8 via r0) character_table_hook: lsr r0, #0x18 cmp r1, #2 @ check gender < 2 blo character_table_normal @@ Load custom table adr r3, character_table_custom sub r1, #2 @ (gender - 2) * 6 lsl r2, r1, #2 sub r2, r1 lsl r2, #1 add r3, r2 add r0, r3 ldrb r0, [r1] bx lr character_table_normal: lsl r0, #1 add r1, r0 add r1, r2 ldrb r0, [r1] bx lr .align 2 @@ Select overworld numbers for your new character character_table_custom: .byte 0 @ walking .byte 1 @ biking .byte 2 @ sitting (surfing) .byte 3 @ vs seeker/pokeball .byte 4 @ fishing .byte 5 @ vs seeker/pokeball
This probably will only refresh when you change map, so use the next hack.
Instant NPC sprite switch
This is related to the last hack, but can be more useful for a less permanent change. It can also work on other NPCs. Callasm as usual with the NPC person number in 0x8000 (same ID you use with applymovement - and 0xFF for the player) and the target sprite (the sprite index you'd use in advance map) in 0x8001.
Code untested.
It would be cool if someone could test these and write example scripts. I am too lazy.Spoiler:
Code:.align 2 .thumb instant_npc_frame_switch: push {r4-r6, lr} sub sp, #4 ldr r4, variables @@ Determine npc state id from person id ldr r0, saveblock1_mapdata ldr r0, [r0] ldrb r0, [r4] @ person/local ID from var 0x8000 ldrb r1, [r0, #5] @ current map ldrb r2, [r0, #4] @ current bank mov r3, sp ldr r5, npc_id_by_local_id_and_map_ret_success bl call_via_r5 cmp r0, #0 @ failure check bne instant_npc_frame_switch_return @@ Get npc_state mov r0, sp ldrb r1, [r0] @ npc_id lsl r0, r1, #3 @ npc_states + 0x24 * npc_id add r0, r1 lsl r0, #2 ldr r1, npc_states add r6, r0, r1 @@ Change Sprite mov r0, r6 @ npc_state ldrb r1, [r4, #2] @ sprite index from var 0x8001 ldr r5, npc_change_sprite bl call_via_r5 @@ Update direction to prevent graphical artifacts mov r0, r6 ldrb r1, [r0, #0x18] @ npc direction lsr r1, #4 ldr r5, npc_turn bl call_via_r5 instant_npc_frame_switch_return: add sp, #4 pop {r4-r6, pc} call_via_r5: bx r5 .align 2 variables: .word 0x020370B8 @ script var 0x8000 saveblock1_mapdata: .word 0x03005008 npc_states: .word 0x02036E38 npc_change_sprite: .word 0x081507BC + 1 npc_turn: .word 0x0805F218 + 1 npc_id_by_local_id_and_map_ret_success: .word 0x0805DF84 + 1
Pre-battle Mugshot Hack in BPEE
I don't hack Emerald but my friend jirachiwishmaker requested the code, so I will share it.
This is a port of Jambo51's codes in this thread to Emerald Version
If you still don't know what it is, please take a look at this picture:
![]()
1. Make these byte changes:
Code:0x147C6A - 00 00 00 00 (disable the palette mixing) 0xB13FD - 78 (for safety's sake) 0x5C8F90 - CD 6A 0F 73 51 7B 93 7F D5 7F FF 7F (filling the palette...) 0x5C8F70 - CD 6A 0F 73 51 7B 93 7F D5 7F FF 7F 0x5C8F50 - CD 6A 0F 73 51 7B 93 7F D5 7F FF 7F
2. Insert these 3 ASM codes in free space and change bytes accordingly:
insert 00 48 00 47 AA AA AA 08 at 0xB0F44, in which AA AA AA 08 is the pointer to the following routine (thumb mode +1)
Code:.thumb .align 2 ldrb r2, [r4, #7] cmp r2, #0 beq normal ldr r0, =0x80B0F5D bx r0 normal: ldrh r2, [r4] lsl r0, r2, #2 add r0, r0, r2 lsl r0, r0, #3 add r0, r0, r1 ldr r1, =0x80B0F4F bx r1
insert 00 48 00 47 BB BB BB 08 at 0xB5E78, BB BB BB 08 = pointer to the following code (thumb mode +1)
Code:.thumb .align 2 cmp r4, #0x47 beq normal cmp r4, #0x48 beq normal ldr r0, =0x2038BCA ldrh r0, [r0] lsl r5, r0, #2 add r5, r0, r5 lsl r0, r5, #3 ldr r5, =0x806E4C4 ldr r5, [r5] add r0, r0, r5 ldrb r4, [r0, #3] normal: add r5, r1, #0 add r6, r2, #0 mov r9, r3 ldr r7, [sp, #0x34] ldr r0, =0x80B5E81 bx r0
insert 01 49 08 47 00 00 CC CC CC 08 at 0x147C42, CC CC CC 08 = pointer to the following code (thumb mode +1)
change 0x8FFFFFF to the palette table in your ROM and it can have 255 custom palettes.
The table's structure is [pointer1][pointer2]........................
Every pointer will point to a 16-color uncompressed palette (32 bytes)
Code:.thumb main: ldr r1, ramoffset ldrh r1, [r1, #0x0] lsl r0, r1, #0x2 add r0, r0, r1 lsl r1, r0, #0x3 ldr r0, trainertable ldr r0, [r0, #0x0] add r1, r0, r1 ldrb r1, [r1, #0x1] cmp r1, #0x1f beq oldway cmp r1, #0x26 beq oldway ldr r1, ramoffset ldrb r1, [r1, #0x7] sub r1, #0x1 lsl r1, r1, #0x2 ldr r0, table2 add r1, r1, r0 ldr r0, [r1, #0x0] b back oldway: ldr r1, table mov r2, r8 mov r3, #0x26 ldrh r0, [r2, r3] lsl r0, r0, #0x2 add r0, r0, r1 ldr r0, [r0, #0x0] back: ldr r1, return bx r1 .align 2 ramoffset: .word 0x02038BCA trainertable: .word 0x0806E4C4 table: .word 0x085C8FDC table2: .word 0x08FFFFFF return: .word 0x08147C51
To activate it in a script, you can use this format:
0x0100 means the first palette in your custom table at 0x8FFFFFF, and 0x0200 means the second, ...... 0xff00 means the 255th palette.Code:trainerbattle 0(type, you can change it to fit your script) 0x50(your chosen trainer's ID) [b]0x0100[/b] @pointertomsg1 @pointertomsg2
Some sample palettes in the original game: (If you don't change the tiles and tileset, please build your palette in this format using APE)
Code:D5 18 CE 39 52 4A D6 5A 5A 6B 17 5C 59 64 9B 6C DD 74 1F 7D CD 6A 0F 73 51 7B 93 7F D5 7F FF 7F
Give credit to Jambo51 (for the routines for BPRE) and jirachiwishmaker (for finding some offsets) if you use this hack. I only adjusted the routines so that it will be compatible with Emerald's RAM structure and fixed a small glitch in Jambo51's code1. So no credit needed for me, if you don't want to make your credit list long.Code:D5 18 CE 39 52 4A D6 5A 5A 6B 41 07 A4 13 C6 1B E9 27 EF 3F FC 45 3E 4E 7F 56 BF 5E FF 66 FC 45