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)

chrunch September 7th, 2015 1:45 AM

Quote:

Originally Posted by DizzyEgg (Post 8918957)
You probably messed up pointers. Try doing it again and make sure all your pointers are correct.



It seems that TMs are still consumable if taught to a pokemon without animation, i.e. if it only knows 2 moves.

There's already a fix for this here.

avantimaestro September 7th, 2015 8:21 AM

Quote:

Originally Posted by Lance32497 (Post 8915656)
Hello, since the EXP. Gain canceller had been effin'ly implemented, it's good to have MONEY gain and reduce canceller so that we can make a Battle frontier-like event.
Request

Temporarily disabling prize money from battle

(Only works in FireRed)

Here is a routine that will prevent you from getting money after you won a battle against a trainer. Good for tournament-style battles, where it makes no sense that you get or lose money.

How to insert:

Compile and insert this routine anywhere 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, #0x5
    ldr r2, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r2, =(0x809FDA0 +1)
    bl linker
    ldr r1, =(0x8025A00 +1)
    bx r1

skip:
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r1, =(0x8025A00 +1)
    bx r1

linker:
    bx r2

.align 2


(not really space saving, i know...)

Compiled:
Code:

0F B4 FF 20 40 00 05 30 0E 4A 00 F0 19 F8 01 28 0C D0 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 09 4A 00 F0 0C F8 08 49 08 47 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 03 49 08 47 10 47 C0 46 D1 E6 06 08 A1 FD 09 08 01 5A 02 08



Now navigate to 0x0259E8 and insert following bytes:
Code:

00 48 00 47 XX XX XX 08


Where XX XX XX is the location of the routine you inserted + 1.


Next compile and insert this routine into free space:
Spoiler:
Code:

.text
.align 2
.thumb
.thumb_func

main:
    mov r0, #0xFF
    lsl r0, r0, #0x1
    add r0, r0, #0x5
    ldr r2, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip
    add r0, r4, #0x0
    ldr r2, =(0x809fdd8 +1)
    bl linker

skip:
    ldr r2, =(0x80a0058 +1)
    bl linker
    ldr r2, =(0x8054BEA +1)

linker:
    bx r2

.align 2


Compiled:
Code:

FF 20 40 00 05 30 07 4A 00 F0 0A F8 01 28 03 D0 20 1C 05 4A 00 F0 04 F8 04 4A 00 F0 01 F8 04 4A 10 47 C0 46 D1 E6 06 08 D9 FD 09 08 59 00 0A 08 EB 4B 05 08



Finally navigate to 0x054BE0 and insert following bytes where XX XX XX is the location of the second routine +1:
Code:

00 48 00 47 XX XX XX 08


This thing requires two routines, that's because the money gets reduced when you black out while the prize money is gained after the message appears. These are two different places so there have to be two different functions :P


At last you should also want to remove the text that appears after winning/losing that informs you about the money you gained/lost. You need another routine for that. Compile and insert into free space:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
    ldr r0, =(0x83fb432)
    cmp r2, r0
    beq checkflag
    ldr r0, =(0x83fb4f6)
    cmp r2, r0
    beq checkflag
    b noskip

checkflag:
    mov r0, #0xFF
    lsl r0, r0, #0x1
    add r0, r0, #0x5
    ldr r3, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip

noskip:
    ldr r0, =(0x202298C)
    mov r1, #0x0
    ldr r3, =(0x80D87BC +1)
    bl linker

skip:
    ldr r0, =(0x8032B4C +1)
    bx r0

linker:
    bx r3

.align 2


Compiled:
Code:

0B 48 82 42 03 D0 0B 48 82 42 00 D0 07 E0 FF 20 40 00 05 30 08 4B 00 F0 09 F8 01 28 04 D0 07 48 00 21 07 4B 00 F0 02 F8 06 48 00 47 18 47 C0 46 32 B4 3F 08 F6 B4 3F 08 D1 E6 06 08 8C 29 02 02 BD 87 0D 08 4D 2B 03 08



Now change the bytes at 0x032B44 to following (XX XX XX) is the location of this last routine:
Code:

00 48 00 47 XX XX XX 08


How to use:

In order to disable prize money you have to set the flag 0x203.
If you want to reenable it just clear the flag and you will get money again.

Joexv September 7th, 2015 11:15 AM

Quote:

Originally Posted by NylonGamer (Post 8919240)
Temporarily disabling prize money from battle


Here is a routine that will prevent you from getting money after you won a battle against a trainer. Note that the message telling you about your prize money still shows up, iI am working on that. I'll update the post later with the final version because I don't have much time today. EDIT: I just realized ita lso doesn't work when you lose, so just wait a bit and dont insert it yet...


How to insert:

Compile and insert this routine anywhere 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, #0x5
    ldr r2, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r2, =(0x809FDA0 +1)
    bl linker
    ldr r1, =(0x8025A00 +1)
    bx r1

skip:
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r1, =(0x8025A00 +1)
    bx r1

linker:
    bx r2

.align 2


(not really space saving, i know...)

Compiled:
Code:

0F B4 FF 20 40 00 05 30 0E 4A 00 F0 19 F8 01 28 0C D0 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 09 4A 00 F0 0C F8 08 49 08 47 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 03 49 08 47 10 47 C0 46 D1 E6 06 08 A1 FD 09 08 01 5A 02 08




Now navigate to 0x0259E8 and insert following bytes:
Code:

00 48 00 47 XX XX XX 08


Where XX XX XX is the location of the routine you inserted + 1.


How to use:

In order to disable prize money you have to set the flag 0x203.
If you want to reenable it just clear the flag and you will get money again.

The location of the text is 0x3FB41A, there seem to be only one pointer to it, its setup in a table along with various other winning/losing messages which appears to start at 0x3FDF3C. Hope this helps.

partys over September 7th, 2015 12:08 PM

Quote:

Originally Posted by DizzyEgg (Post 8918957)
You probably messed up pointers. Try doing it again and make sure all your pointers are correct.



It seems that TMs are still consumable if taught to a pokemon without animation, i.e. if it only knows 2 moves.

Quote:

Where XX XX XX is the location of the routine you inserted + 1.
I don't really get what the "+1" means. That's probably where I messed up.

Deokishisu September 7th, 2015 7:11 PM

Quote:

Originally Posted by FrogInfected (Post 8919488)
I don't really get what the "+1" means. That's probably where I messed up.

If you put the routine at 0x800000, your pointer would NOT be 00 00 80 08, it would be 01 00 80 08, as if the location was 0x800001. It's a THUMB quirk, I think.

Pokemon_XY September 8th, 2015 12:20 AM

I would like to make a request: wild double battle in Pkmn FR version
Based on JPAN's document on battle scripts, we can change a word in the EWRAM to change the battle type. However, simply putting a hook at the function storing type to that location is obviously with several bugs so I hope that someone will get the full source code and share it, thanks!

esperance September 8th, 2015 4:19 PM

Day/Night Switching of Textbox Palettes (FireRed)


So this is one of my few successful ASM hacks. What it does is swap the palettes used by the textbox depending on whether it is day or night (based on Prime Dialga's D/N system). Some of you older users may remember such a feature being implemented by Shiny Quagsire for Pokémon Grey (iirc).

So the first thing you need to do is go to 0x471DEC and copy 0xA0 bytes there, and then paste them into freespace somewhere. Be sure to note the offset. These are the five palettes used by the textboxes. You can use this copy as the base for your new night palettes.

Next, assemble and insert the following routine into freespace, once again noting the offset. Be sure to replace the ZZZZZZ with the offset of your new night palettes.
Code:

.text
.align 2
.thumb
.thumb_func

main:
  @ get the time
  ldr r1, =(0x300553C) @ if your RTC uses a different location for the time, change this
  ldrb r1, [r1, #0x6]

  @ check the time
  @ if <= 6 AM or >= 6 PM
  @  load night palette
  @ else
  @  load day palette
  cmp r1, #0x6 @ 6 AM
  ble set_night
  cmp r1, #0x12 @ 6 PM
  bge set_night

set_day:
  ldr r1, day_palette
  b return

set_night:
  ldr r1, night_palette

return:
  @ this uses the end of the original function
  @ so there should be no problems
  add r0, r0, r1
  pop {r1}
  bx r1

.align 2

day_palette:
  .word 0x08471DEC

night_palette:
  .word 0x08ZZZZZZ @ change this to your night palette


Now finally, navigate to 0x150448 and place this (the hook):
Code:

00 49 08 47 XX XX XX 08 00 00 00 00


Where XX XX XX 08 is the pointer to the location you inserted the ASM + 1.

I know it's a bit of a silly hack, but I hope someone makes use of it! :)

partys over September 10th, 2015 8:13 PM

Quote:

Originally Posted by Deokishisu (Post 8919895)
If you put the routine at 0x800000, your pointer would NOT be 00 00 80 08, it would be 01 00 80 08, as if the location was 0x800001. It's a THUMB quirk, I think.

So it's just +1 for the first byte? Also, for every asm pointer, do I always have to add +1?

chrunch September 11th, 2015 1:44 AM

Quote:

Originally Posted by FrogInfected (Post 8923203)
So it's just +1 for the first byte? Also, for every asm pointer, do I always have to add +1?

Yes, and no only if it says to.

Pokemon_XY September 11th, 2015 7:20 AM

Quote:

Originally Posted by FrogInfected (Post 8923203)
for every asm pointer, do I always have to add +1?

No, that depends on the way to jump to the code.
If you use bx (or callasm in script, which also use bx to jump to the code), you should add 1 if the code is in thumb mode as is always the case.
If you use another way to branch, such as
Code:

ldr r0, .addr
mov pc, r0
.align 2
.addr: [offset of your code]


This kind of code don't need to add 1 to the pointer of the code it jumps to.
But most people use bx to jump, so adding 1 is often required.

Splash September 11th, 2015 7:44 AM

ASM Request:
Sneak Mechanic from ORAS
Function:
Slowing down the movement that will give you higher chance of encountering shiny pokemon or pokemon with egg moves.

partys over September 11th, 2015 8:04 PM

Quote:

Originally Posted by chrunch (Post 8923390)
Yes, and no only if it says to.

Alright, thanks guys. Pretty new to asm, as you can tell.

kleenexfeu September 12th, 2015 9:51 AM

I know there's several routines like this one, but I didn't found them practical.

Check a specific pokémon with a specific slot through the use of Special 0xA2, for Emerald :
Spoiler:

Code:

.thumb

Start:
        push {r0-r7, lr}
        ldr r6, var8005
        ldr r0, party_amount
        ldrb r4, [r0]
        cmp r4, #0x0
        beq End
        ldrh r3, [r6]
        cmp r3, #0x0
        beq End
Check:
        add r0, #3
        mov r1, #0x64
        ldr r7, var8004
        ldrb r6, [r7]
        mul r1, r6
        add r0, r0, r1
        push {r0-r7}
        mov r1, #0xB
        ldr r2, decrypt_poke
        bl Jump
        mov r9, r0
        pop {r0-r7}
        cmp r9, r3
        bne NoSuccess
        mov r6, #1
        b Success
NoSuccess:
        mov r6, #0
Success:
        ldr r7, var8005
        strh r6, [r7]

End:
        pop {r0-r7, pc}
Jump:
mov pc, r2

.align 2
party_amount:        .word 0x020244E9
var8004:                .word 0x020275D8 + (0x8004*2)
var8005:                .word 0x020275D8 + (0x8005*2)
decrypt_poke:        .word 0x0806A519

/*var 0x8005, species you want to check*/


Basically, when you use special 0xA2, the party screen open and you can select a poke, the slot of the poke is stored in var 0x8004, so the routine check this slot.
If it is the the same species than 0x8005, then 0x8005 is set to 1, otherwise to 0

Le pug September 12th, 2015 5:17 PM

Quote:

Originally Posted by NylonGamer (Post 8919240)
Spoiler:
Temporarily disabling prize money from battle


Here is a routine that will prevent you from getting money after you won a battle against a trainer. Good for tournament-style battles, where it makes no sense that you get or lose money.

How to insert:

Compile and insert this routine anywhere 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, #0x5
    ldr r2, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r2, =(0x809FDA0 +1)
    bl linker
    ldr r1, =(0x8025A00 +1)
    bx r1

skip:
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r1, =(0x8025A00 +1)
    bx r1

linker:
    bx r2

.align 2


(not really space saving, i know...)

Compiled:
Code:

0F B4 FF 20 40 00 05 30 0E 4A 00 F0 19 F8 01 28 0C D0 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 09 4A 00 F0 0C F8 08 49 08 47 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 03 49 08 47 10 47 C0 46 D1 E6 06 08 A1 FD 09 08 01 5A 02 08



Now navigate to 0x0259E8 and insert following bytes:
Code:

00 48 00 47 XX XX XX 08


Where XX XX XX is the location of the routine you inserted + 1.


Next compile and insert this routine into free space:
Spoiler:
Code:

.text
.align 2
.thumb
.thumb_func

main:
    mov r0, #0xFF
    lsl r0, r0, #0x1
    add r0, r0, #0x5
    ldr r2, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip
    add r0, r4, #0x0
    ldr r2, =(0x809fdd8 +1)
    bl linker

skip:
    ldr r2, =(0x80a0058 +1)
    bl linker
    ldr r2, =(0x8054BEA +1)

linker:
    bx r2

.align 2


Compiled:
Code:

FF 20 40 00 05 30 07 4A 00 F0 0A F8 01 28 03 D0 20 1C 05 4A 00 F0 04 F8 04 4A 00 F0 01 F8 04 4A 10 47 C0 46 D1 E6 06 08 D9 FD 09 08 59 00 0A 08 EB 4B 05 08



Finally navigate to 0x054BE0 and insert following bytes where XX XX XX is the location of the second routine +1:
Code:

00 48 00 47 XX XX XX 08


This thing requires two routines, that's because the money gets reduced when you black out while the prize money is gained after the message appears. These are two different places so there have to be two different functions :P


At last you should also want to remove the text that appears after winning/losing that informs you about the money you gained/lost. You need another routine for that. Compile and insert into free space:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
    ldr r0, =(0x83fb432)
    cmp r2, r0
    beq checkflag
    ldr r0, =(0x83fb4f6)
    cmp r2, r0
    beq checkflag
    b noskip

checkflag:
    mov r0, #0xFF
    lsl r0, r0, #0x1
    add r0, r0, #0x5
    ldr r3, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip

noskip:
    ldr r0, =(0x202298C)
    mov r1, #0x0
    ldr r3, =(0x80D87BC +1)
    bl linker

skip:
    ldr r0, =(0x8032B4C +1)
    bx r0

linker:
    bx r3

.align 2


Compiled:
Code:

0B 48 82 42 03 D0 0B 48 82 42 00 D0 07 E0 FF 20 40 00 05 30 08 4B 00 F0 09 F8 01 28 04 D0 07 48 00 21 07 4B 00 F0 02 F8 06 48 00 47 18 47 C0 46 32 B4 3F 08 F6 B4 3F 08 D1 E6 06 08 8C 29 02 02 BD 87 0D 08 4D 2B 03 08



Now change the bytes at 0x032B44 to following (XX XX XX) is the location of this last routine:
Code:

00 48 00 47 XX XX XX 08


How to use:

In order to disable prize money you have to set the flag 0x203.
If you want to reenable it just clear the flag and you will get money again.

Requesting this in Emerald. Great resource and besides tournaments, it can be used for trainer-battle styled wild pokemon battles (obviously they dont give you $)

Ephraim225 September 13th, 2015 2:11 PM

Checking HM Compatibility
Hey guys, I've got a fun one for you. If you're like me and hate wasting move slots on HMs, this hack will make that a thing of the past. This hack checks whether the player's team contains a Pokemon that can learn an HM you specify. It doesn't check if they actually HAVE it, only whether they CAN learn it. Used correctly, the player can simply walk up to a tree and cut it immediately if they have a Pokémon that can cut. This is for Fire Red but porting it should be simple if you know the equivalent offsets in Emerald (and I don't, if someone does, let me know and I'll update this post)

Compile and insert to free space:
Spoiler:
.align 2
.thumb

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

loopback:
ldr r0, =(0x2024284) /* Player's party in RAM */
mov r2, #0x64
mov r1, r5
mul r1, r1, r2
add r0, r0, r1
mov r1, #0xB
ldr r3, =(0x803FBE8 +1) /* Pokemon decrypter */
bl linker

ldr r3, =(0x8252BD0) /* TM Compatibility table */
lsl r0, r0, #0x3
add r3, r0, r3
add r3, r3, #0x6
ldrb r2, [r3]
ldr r1, =(0x20370D0) /* Var 0x800D in RAM */
ldrb r0, [r1]
mov r3, r0
and r3, r2, r3
cmp r0, r3
beq end

ldr r3, =(0x2024029) /* Player's team size */
ldrb r3, [r3]
add r5, r5, #0x1
cmp r5, r3
beq endfail
b loopback

end:
strb r5, [r1]
pop {r0-r5, pc}

endfail:
mov r5, #0x6
strb r5, [r1]
pop {r0-r5, pc}

linker:
bx r3


NOTE: Before you compile, direct your attention to the line highlighted in blue. The offset here is the offset of the table that determines TM/HM compatibility. If you have expanded the number of Pokémon in your hack, be sure to change this offset to whatever the new offset is.

Now, using this ASM is simple. In whatever script you're writing, first set variable 0x800D (aka LASTRESULT) to one of the following values based on the HM you are checking:

Spoiler:
0x4 - Cut
0x8 - Fly
0x10 - Surf
0x20 - Strength
0x40 - Flash
0x80 - Rock Smash


Then, call the ASM using Callasm. After the ASM runs, variable 0x800D will be set to the party slot containing the Pokémon who can learn whatever move you checked for, or 0x6 if no Pokémon was found.

The only issue is, Fly and Flash aren't used in scripts by the game, and Dive and Waterfall can't be checked. Making items that perform the same functions using other methods, however, is a working substitute.

Here's an example script. Let's say I'm editing the cut tree script. (If you remove the badge check and attack check as I have you can actually overwrite the original script with this, as there's enough space for it)
Spoiler:
#org 0x81BDF13
'-----------------------------------
special INIT_STEPCOUNT
compare LASTRESULT 0x2
if == jump 0x81A7AE0 ' Equal To
lockall
setvar LASTRESULT 0x4
callasm 0x8XXXXXX ' This should be changed to wherever you put the ASM in your ROM

compare LASTRESULT 0x6
if == jump 0x81BDF87 ' This skips the rest of the script if 0x6 is returned
setanimation 0x0 0x800D
storepartypokemon 0x0 0x800D
storeattack 0x1 0xF
msgbox 0x81BDF94 ' This tree looks like...
callstd MSG_YESNO ' Yes/No message
compare LASTRESULT NO
if == jump 0x81BDF91 ' Equal To
msgbox 0x81BDFD7 ' \v\h02 used \v\h03!
callstd MSG_NOCLOSE ' Non-closing message
closemsg
doanimation 0x2
waitspecial
jump 0x81BDF76


Anyways, that's that. I'll be using this in the future, but I do hope others can make use of it too.

Blah September 13th, 2015 2:22 PM

Quote:

Originally Posted by Ephraim225 (Post 8927083)
Checking HM Compatibility
Hey guys, I've got a fun one for you. If you're like me and hate wasting move slots on HMs, this hack will make that a thing of the past. This hack checks whether the player's team contains a Pokemon that can learn an HM you specify. It doesn't check if they actually HAVE it, only whether they CAN learn it. Used correctly, the player can simply walk up to a tree and cut it immediately if they have a Pokémon that can cut. This is for Fire Red but porting it should be simple if you know the equivalent offsets in Emerald (and I don't, if someone does, let me know and I'll update this post)

Compile and insert to free space:
Spoiler:
.align 2
.thumb

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

loopback:
ldr r0, =(0x2024284) /* Player's party in RAM */
mov r2, #0x64
mov r1, r5
mul r1, r1, r2
add r0, r0, r1
mov r1, #0xB
ldr r3, =(0x803FBE8 +1) /* Pokemon decrypter */
bl linker

ldr r3, =(0x8252BD0) /* TM Compatibility table */
lsl r0, r0, #0x3
add r3, r0, r3
add r3, r3, #0x6
ldrb r2, [r3]
ldr r1, =(0x20370D0) /* Var 0x800D in RAM */
ldrb r0, [r1]
mov r3, r0
and r3, r2, r3
cmp r0, r3
beq end

ldr r3, =(0x2024029) /* Player's team size */
ldrb r3, [r3]
add r5, r5, #0x1
cmp r5, r3
beq endfail
b loopback

end:
strb r5, [r1]
pop {r0-r5, pc}

endfail:
mov r5, #0x6
strb r5, [r1]
pop {r0-r5, pc}

linker:
bx r3


NOTE: Before you compile, direct your attention to the line highlighted in blue. The offset here is the offset of the table that determines TM/HM compatibility. If you have expanded the number of Pokémon in your hack, be sure to change this offset to whatever the new offset is.

Now, using this ASM is simple. In whatever script you're writing, first set variable 0x800D (aka LASTRESULT) to one of the following values based on the HM you are checking:

Spoiler:
0x4 - Cut
0x8 - Fly
0x10 - Surf
0x20 - Strength
0x40 - Flash
0x80 - Rock Smash


Then, call the ASM using Callasm. After the ASM runs, variable 0x800D will be set to the party slot containing the Pokémon who can learn whatever move you checked for, or 0x6 if no Pokémon was found.

The only issue is, Fly and Flash aren't used in scripts by the game, and Dive and Waterfall can't be checked. Making items that perform the same functions using other methods, however, is a working substitute.

Here's an example script. Let's say I'm editing the cut tree script. (If you remove the badge check and attack check as I have you can actually overwrite the original script with this, as there's enough space for it)
Spoiler:
#org 0x81BDF13
'-----------------------------------
special INIT_STEPCOUNT
compare LASTRESULT 0x2
if == jump 0x81A7AE0 ' Equal To
lockall
setvar LASTRESULT 0x4
callasm 0x8XXXXXX ' This should be changed to wherever you put the ASM in your ROM

compare LASTRESULT 0x6
if == jump 0x81BDF87 ' This skips the rest of the script if 0x6 is returned
setanimation 0x0 0x800D
storepartypokemon 0x0 0x800D
storeattack 0x1 0xF
msgbox 0x81BDF94 ' This tree looks like...
callstd MSG_YESNO ' Yes/No message
compare LASTRESULT NO
if == jump 0x81BDF91 ' Equal To
msgbox 0x81BDFD7 ' \v\h02 used \v\h03!
callstd MSG_NOCLOSE ' Non-closing message
closemsg
doanimation 0x2
waitspecial
jump 0x81BDF76


Anyways, that's that. I'll be using this in the future, but I do hope others can make use of it too.

First of all, good job! As for the issues with Surf, Waterfall and Fly, I think these links would help you a good amount:
http://www.pokecommunity.com/showthread.php?t=338513
http://www.pokecommunity.com/showpost.php?p=8676227&postcount=530

Lastly, just a small tip.
Code:

cmp r5, r3
beq endfail
b loopback


When you have two branches in a row (and one or both aren't "bl") it can be reduced to a single branch. Here bne loopback would do the same as these two branches if you move endfail as the next line in sequence :)

Z-nogyroP September 14th, 2015 3:25 AM

Hey, I'm not sure if this is the correct place to put this, but I used KDS's script for the Wide Lens in my hack. It compiled properly and everything, but the game isn't letting me hold the item, so I can't test if it actually worked.

Where's the check that says whether or not an item can be held?

Pokemon_XY September 18th, 2015 3:20 AM

Quote:

Originally Posted by FBI (Post 8512782)
I don't know where it is either. Perhaps you can ask daniilS via VM or something.




1) For forced evolution, I don't know what you're really talking about. You mean just make a Pokemon evolve without giving the player time to hit the "b" button? I'll look into Pokemon evolution sure.

2) I haven't seen it so VMing me it would be nice. Anyways this is rather easy, I've done it before. I'll post the results at the bottom of this post.

3) Skipping the introduction was already done by Knizz. There's a post in the research and development section's quick research thread.


Preventing TMs from being consumed on use



Quick research:
TMs are deleted in two places. The first place is in their own function. When called from the bag, after use the TM has it's own deletion mechanism. The second way is from the bag, after you use a TM the bag attempts to delete it as well. Well, the solution is quite simple. There's two ways to do this, either go to 0809A1D8 call your own function there which checks if the item is a TM, and if it is, just jump to the end. Or much more simply you just remove the parts from the bag and tm function that deletes the TM (Which is what I did). The former way is a way you can make another item you have unconsumable.

To insert:
Do the byte changes below
0x124F78: 00 00 00 00
0x125C80: 00 00 00 00

Make it Ungivable:
insert that at 0x1326B8: 00 00 17 E0

Make it consumable after animation:
Insert: 00 00 00 00 at 0x124F78

To remove the quantities showing up in the bag:

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




Here's a compiled version:
Code:

00 2D 01 D1 05 4B 18 47 38 1C 08 21 22 1C 04 4E 00 F0 02 F8 01 4B 18 47 30 47 C0 46 FF 1E 13 08 B1 35 13 08


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

Unsellable:
Basically for the TMs, you can still sell them to vendors. To change this, you need to modify each TM individually. It's unfortunate, but the game checks if an item can be sold my comparing it's market price to zero. If it's strictly greater than zero, then you can sell it to a vendor, seems to be the rule. So to make TMs unsellable you need to set their market prices individually to zero.
I can't use my own checks to disguise the TMs as unique because the sell routine in shops are used for ALL items including potions, berries, TMs, and other items like nuggets.


Present :3
http://i.imgur.com/3nina1p.png?1

I've found a way to make TMs unsellable:
Code:

0x132924 - 00 00 00 00


In addition, the quantity in bag when you buy TMs in the game should be hided, and here is a quick way to remove the box which shows the quantity for all items:
Code:

0x9BCC2 - 00 00 00 00


So here's the full code, no extra routines needed

Reusable TMs


Code:

0x1326BA - 17 E0 //can't hold as item
0x124F78 - 00 00 00 00 //can't delete
0x125C80 - 00 00 00 00 //can't delete
0x124EAC - 00 00 00 00 //can't delete
0x131EA6 - 2A E0 //fix the graphic
0x132924 - 00 00 00 00 //can't sell
0x9BCC2 - 00 00 00 00 //hide the box showing quantity


My contribution:

Forcing the text speed to "fast"


It is done by neglecting the speed set by the player:
Code:

0xF78D0 - 01 20


Then everything is done automatically.

robinjea September 19th, 2015 2:35 PM

Quote:

Originally Posted by Pokemon_XY (Post 8933435)
I've found a way to make TMs unsellable:
Code:

0x132924 - 00 00 00 00


In addition, the quantity in bag when you buy TMs in the game should be hided, and here is a quick way to remove the box which shows the quantity for all items:
Code:

0x9BCC2 - 00 00 00 00


So here's the full code, no extra routines needed

Reusable TMs


Code:

0x1326BA - 17 E0 //can't hold as item
0x124F78 - 00 00 00 00 //can't delete
0x125C80 - 00 00 00 00 //can't delete
0x124EAC - 00 00 00 00 //can't delete
0x131EA6 - 2A E0 //fix the graphic
0x132924 - 00 00 00 00 //can't sell
0x9BCC2 - 00 00 00 00 //hide the box showing quantity


My contribution:

Forcing the text speed to "fast"


It is done by neglecting the speed set by the player:
Code:

0xF78D0 - 01 20


Then everything is done automatically.

Umm... Hi. I believe I don't understand the implication of your comment "//can't delete". Does this mean I can't delete the attack I taught using a TM?

Pokemon_XY September 19th, 2015 6:53 PM

Quote:

Originally Posted by BlackWhiteRobin (Post 8935100)
Umm... Hi. I believe I don't understand the implication of your comment "//can't delete". Does this mean I can't delete the attack I taught using a TM?

It means that it won't be deleted even it's used so that's just part of this hack. (It is from FBI's hack so please don't worry about it)

jiangzhengwenjzw September 20th, 2015 2:20 AM

1 Attachment(s)

The implementation of ROCK CLIMB in BPRE


This post will only deal with the "rock climb" selected by the player in the pokemon selection scene, so please do the script on your own if you want to use rock climb by talking to a rock.
This hack can judge the "playerfacing" and the number of the blocks you will climb.
1. Firstly we will repoint and expand the RAM location for TMs: (found from Development: More TMs/HMs - The PokéCommunity Forums Credit goes to Taの境界)
at 0x99E6A:
Code:

01 48 00 47 00 00 FF FF FF 08


FF FF FF 08 is the pointer to ram.asm (thumb mode +1):
ram.asm:
Code:

.text
.align 2
.thumb
.thumb_func
.global tm_slots_hack

main:
ldr r0, ram
str r0, [r1, #0x18]
mov r0, #0x3B
strb r0, [r1, #0x1c]
ldr r0, return
bx r0

.align
ram:.word 0x0203c000
return:.word 0x08099e74+1


0x203c000 is the free ram location.

2. Use JPAN's save_block_hack to save properly.
link: The PokéCommunity Forums - View Single Post - Research: FireRed Pokédex Hacking
Or use the patch instead: JPAN's Save Block Patch for FR » Romhack.me - ROM Hacking Community

3. tables and codes
1)repoint the table at 0x45A76E, replace 0c 00 with the move id of rock climb (swapped), and put 0c 00 after it as the end. (special move table)
2)repoint the table at 0x45A80C, add the move id (swapped). (TM table)
3)repoint the table at 0x45A37C and add an pointer to the description text. Please make it short like other texts in this table. (description text pointer table)
4)repoint the table at 0x45A618 and add [pointer to move name] A5 45 12 08 at the end of the table. (name_table)
5)copy these data to 0x3D4D6C as item picture and palette data.
Code:

C8 1C E9 08 64 1E E9 08


(in item picture & palette table)
6)copy these data to 0x3DEBCC as item data. (in item table)
Code:

C2 C7 A1 AA FF 00 00 00 00 00 00 00 00 00 5B 01 00 00 00 00 E5 75 48 08 01 00 04 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00


Please edit the description pointer to your new description!
7)edit the table at 0x252BC8 to enable some pokemon to learn the HM. This table is made up with bitfield, which means that you should convert it into binary to see the real data. 1 = learnable 0 = can't learn(TM learnable table)
For example, data for bulbasaur is "20 07 35 84 08 1E E4 00"
We divide it into 2 parts: "20 07 35 84" and "08 1E E4 00"
Then swap them, so we get "84350720" and "00E41E08"
Convert them into binary: "10000100001101010000011100100000" and "111001000001111000001000"
get them together in the reversed order:
"11100100000111100000100010000100001101010000011100100000"
It's in the order of "HM08, HM07,.........,TM01"
So if we want bulbusaur to learn HM09 we edit the higher part "111001000001111000001000"
We change it into "100111001000001111000001000"
Then we convert it into hexadecimal: "4E41E08"
swap it to get "08 1E E4 04" and we absolutely use it to replace "08 1E E4 00".
So you can see that we will always only deal with the higher part, I convert the lower part to just make things clearer

8)repoint the table at 0x45A788 and add [XX XX XX 08 0D 00 00 00] to the end of it. (function table)
XX XX XX 08 is the pointer to the following function: (thumb mode +1)
check.asm: (main ROCK CLIMB function)
Code:

.thumb
.align 2
push {r4, lr}
sub sp, sp, #4
mov r4, sp
add r4, #2
mov r0, sp
mov r1, r4
ldr r3, =0x0805C4F5
bl call_via_r3
mov r0, sp
mov r1, #0
ldrsh r0, [r0, r1]
mov r2, #0
ldrsh r1, [r4, r2]
ldr r2, =0x08058F79
bl call_via_r2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
cmp r0, #0x80 @behavior_byte
bne back
ldr r1, =0x03005024
ldr r0, =0x081248B1
str r0, [r1]
ldr r1, =0x0203B0C4
ldr r0, =0x08RRRRRR
str r0, [r1]
mov r0, #1
b real_back

back:
mov r0, #0

real_back:
add sp, sp, #4
pop {r4}
pop {r1}
bx r1

call_via_r3:
bx r3

call_via_r2:
bx r2


change 0x8RRRRRR to the offset+1 of the following function:(script_run function)
Code:

.thumb
.align 2
run_scr:
push {lr}
ldr r0, =0x0203B0A0
ldrb r0, [r0, #9]
ldr r1, =0x020386E0
lsl r0, r0, #0x18
lsr r0, r0, #0x18
str r0, [r1]
ldr r0, =0x08SSSSSS
ldr r1, =0x08069AE5
bl call_via_r1
pop {r0}
bx r0

call_via_r1:
bx r1


change 0x8SSSSSS to the offset of the following script:(ROCK CLIMB script)
Code:

#org @start
lockall
doanimation 0x25
waitstate
callasm 0x8kkkkkk //offset of code1+1
compare 0x800c 1
if1 1 @down
compare 0x800c 2
if1 1 @up
compare 0x800c 3
if1 1 @left
goto @right

#org @down
applymovement 0xff @movedown
waitmovement 0xff
callasm 0x8jjjjjj //offset of code2+1
compare 0x8004 0
if1 1 @downeventual
goto @down

#org @up
applymovement 0xff @moveup
waitmovement 0xff
callasm 0x8jjjjjj //offset of code2+1
compare 0x8004 0
if1 1 @upeventual
goto @up

#org @left
applymovement 0xff @moveleft
waitmovement 0xff
callasm 0x8jjjjjj //offset of code2+1
compare 0x8004 0
if1 1 @lefteventual
goto @left

#org @right
applymovement 0xff @moveright
waitmovement 0xff
callasm 0x8jjjjjj //offset of code2+1
compare 0x8004 0
if1 1 @righteventual
goto @right

#org @downeventual
applymovement 0xff @movedown
waitmovement 0xff
releaseall
end

#org @upeventual
applymovement 0xff @moveup
waitmovement 0xff
releaseall
end

#org @lefteventual
applymovement 0xff @moveleft
waitmovement 0xff
releaseall
end

#org @righteventual
applymovement 0xff @moveright
waitmovement 0xff
releaseall
end

#org @movedown
#raw 0x1D 0xfe

#org @moveup
#raw 0x1e 0xfe

#org @moveleft
#raw 0x1f 0xfe

#org @moveright
#raw 0x20 0xfe


change the 0x8kkkkkk & 0x8jjjjjj to the offset+1 of the following routines.

code1:(get "playerfacing" in var_0x800C)
Code:

.thumb
.align 2
push {lr}
ldr r0, =0x0805C6C5
bl linker
ldr r1, =0x020370D4
strh r0, [r1]
pop {pc}

linker:
bx r0


code2:(get the tile behavior byte)
Code:

.thumb
.align 2
push {r4, lr}
sub sp, sp, #4
mov r4, sp
add r4, #2
mov r0, sp
mov r1, r4
ldr r3, =0x0805C4F5
bl call_via_r3
mov r0, sp
mov r1, #0
ldrsh r0, [r0, r1]
mov r2, #0
ldrsh r1, [r4, r2]
ldr r2, =0x08058F79
bl call_via_r2
lsl r0, r0, #0x18
lsr r0, r0, #0x18
ldr r1, =0x020370C0
cmp r0, #0x80 @behavior_byte
bne back
mov r0, #1
b realback

back:
mov r0, #0

realback:
strh r0, [r1]
add sp, sp, #4
pop {r4, pc}

call_via_r2:
bx r2

call_via_r3:
bx r3


change the "0x80" in code2 and check.asm to the behavior byte you selected for the "rock climb" tile block.

4. fix the badge check routine so that it will check the 8th badge for the HM09 you added: (untested)
place this at 0x12461C:
Code:

00 48 00 47 MM MM MM 08


MM MM MM 08 is the pointer to the following routine: (thumb mode +1)
Code:

.thumb
.align 2
add r0, r4, #0
cmp r4, #7
blt checkbadge
mov r0, #7
cmp r4, #0xc
beq checkbadge
ldr r1, =0x8124627
add r1, #0x32
bx r1

checkbadge:
mov r1, #0x82
lsl r1, r1, #0x4
add r0, r0, r1
ldr r1, =0x8124627
bx r1


5. An example: (Haven't edited the text and name yet)
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/1_zpspkko0bn2.gifhttp://i869.photobucket.com/albums/ab256/jiangzhengwenjz/1_zpsdwugkkzw.png

At last, I have to say that i haven't tried to teach the HM to a pokemon, so if there's any problem, simply follow a reply in Development: More TMs/HMs - The PokéCommunity Forums to delete the animation of learning TMs, but I think there's no problem)

As you can see, I have done the main part, but I can't ensure there's no glitch in this hack. So please contribute to it! I'm so tired with it so i won't touch it recently...

Edit: Here is a simple looping script to get all of the TMs and HMs as the cheats for the game won't work:
Code:

#org @start
lock
faceplayer
setvar 0x8004 0x121
goto @snippet2

//---------------
#org @snippet1
release
end

//---------------
#org @snippet2
additem 0x8004 0x1
addvar 0x8004 0x1
compare 0x8004 0x15C
if 0x1 goto @snippet1
goto @snippet2


Edit2: Source codes and binary files uploaded.

Edit3: Corrected a slight typo. Codes reuploaded.
But please pay attention that "8RRRRRR" & "8SSSSSS" are not in the attachment and they're shown as "8CCCCCC" & "8DDDDDD" in the files in the .zip archive so that they can be compiled successfully. If you don't understand, please simply follow the post and neglect the attachment. So is the offsets included in the script file (scr.rbc) because they use the offset in my test ROM XD

Edit4: added explanation to bitfield.

NewDenverCity September 22nd, 2015 9:39 AM

Events that happen daily:




First of all, this uses the Day/Night System's clock, or you can use ShinyQuagsire's RTC, which I'm fairly sure are one and the same anyway. Either way, you have to have that in the game or this won't work for obvious reasons.


Insert this into free space.
Code:

.thumb
start:
 push {r0-r7, lr}
 ldr r0, =(0x20370D0)
 ldrh r1, [r0]
 mov r2, #0x4
 mul r1, r1, r2
 ldr r0, =(0x3005546)
 add r0, r0, r1
 mov r1, r0
 mov r2, r0
 add r0, #0x1
 add r1, #0x2
 add r2, #0x3
 ldrh r3, [r0]
 ldrb r4, [r1]
 ldrb r5, [r2]
 ldr r6, =(0x300553C)
 ldrh r7, [r6]
 cmp r3, r7
 bcc x800D_1
 strh r7, [r0]
 ldr r6, =(0x300553F)
 ldrb r7, [r6]
 cmp r4, r7
 bcc x800D_1
 strb r7, [r1]
 ldr r6, =(0x3005540)
 ldrb r7, [r6]
 cmp r5, r7
 bcc x800D_1
 strb r7, [r2]
 ldr r0, =(0x20370D0)
 mov r1, #0x0
 strh r1, [r0]
 pop {r0-r7, pc}
x800D_1:
 ldr r6, =(0x300553C)
 ldrh r7, [r6]
 strh r7, [r0]
 ldr r6, =(0x300553F)
 ldrb r7, [r6]
 strh r7, [r1]
 ldr r6, =(0x3005540)
 ldrb r7, [r6]
 strb r7, [r2]
 ldr r0, =(0x20370D0)
 mov r1, #0x1
 strh r1, [r0]
 pop {r0-r7, pc}


This hack uses variable x800D for almost everything. So each event that happens daily is supposed to have a number attached to it using x800D, like so.
Code:

#dynamic 0x______

#org @start
setvar 0x800D 0x_ (set 800D to the table entry.)
callasm 0x8(offset where you put my the previous ASM +1)
compare 0x800D 0x0
if 0x1 goto @1 (if x800D is the value of 0, then the event has already happened today)
compare 0x800D 0x1
if 0x1 goto @2 (if x800D is the value of 1, then the event has not happened that day)


Please credit if you use this, and report any bugs here or by PM/VM, thanks.


~EDIT~ It was pointed out to me that this doesn't work over save data outside of save states, that was an oversight. I'll fix it as soon as I can.

jiangzhengwenjzw September 24th, 2015 1:00 AM

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:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/7-8_zpsiwx42jwk.png
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:
Code:

trainerbattle 0(type, you can change it to fit your script) 0x50(your chosen trainer's ID) 0x0100 @pointertomsg1 @pointertomsg2


0x0100 means the first palette in your custom table at 0x8FFFFFF, and 0x0200 means the second, ...... 0xff00 means the 255th palette.

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


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


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.

Againsts September 24th, 2015 3:56 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 8941047)

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:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/7-8_zpsiwx42jwk.png
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, #6]
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, #0x6]
 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:
Code:

trainerbattle 0(type, you can change it to fit your script) 0x50(your chosen trainer's ID) 0x0100 @pointertomsg1 @pointertomsg2


0x0100 means the first palette in your custom table at 0x8FFFFFF, and 0x0200 means the second, ...... 0xff00 means the 255th palette.

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


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


Give credit to Jambo51 (for the routines for BPRE) and jirachiwishmaker (for finding some offsets). 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.

Worship

Xencleamas September 24th, 2015 7:54 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 8941047)

Pre-battle Mugshot Hack in BPEE


Still don't get the mugshot. I have inserted the routines and done the byte changes correctly but still the mugshot do not appear. Assuming I have modified the script too.

EDIT: It works fine when I use 0x0001, 0x0002, and so on. 0x0100, 0x0200, and so on which are standards to be used for mugshots do not activate well unless you have a palette on that 0x100 slot.

jiangzhengwenjzw September 24th, 2015 3:45 PM

Quote:

Originally Posted by Sky High (Post 8941392)
Still don't get the mugshot. I have inserted the routines and done the byte changes correctly but still the mugshot do not appear. Assuming I have modified the script too.

EDIT: It works fine when I use 0x0001, 0x0002, and so on. 0x0100, 0x0200, and so on which are standards to be used for mugshots do not activate well unless you have a palette on that 0x100 slot.

Sorry, I've corrected routine 1 & routine 3... Now it should work fine with 0x100, 0x200, ... ,0xff00

Pokemon_XY September 25th, 2015 7:33 AM

Please look at following words if you want the custom moves!!!
Firstly to use custom moves you need a routine written by FBI and modified by me which was originally posted here:
Quote:

Code:

0x3EA46 - 01 48 00 47 00 00 XX XX XX 08 //hook


and XX XX XX 08 points to (+1):
Code:

0C B4 1B 48 1B 49 00 F0 21 F8 0C BC 00 28 1E D0 16 4D 00 24 29 1C 09 78 00 29 13 D0 02 21 61 43 49 19 09 88 40 46 14 4B 00 F0 1D F8 01 34 04 2C F0 D1 00 04 49 46 0D 0C 00 9B 10 49 48 45 05 D1 0F 49 08 47 0C 4B 00 F0 0E F8 F2 E7 08 47 40 46 21 1C 00 93 10 B4 08 4C 00 F0 06 F8 10 BC 00 04 49 46 0D 0C 07 4B 18 47 20 47 C0 46 BE 70 03 02 [FF 40 00 00] (Here means var 0x40ff) 69 E5 06 08 B1 E8 03 08 61 EA 03 08 57 EA 03 08 51 EA 03 08



Custom 'givepokemon'


No bugs found in this hack.
Code:

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

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

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

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

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

jump_pc:
pop {pc}

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

jump_r1:
bx r1

jump_r3:
bx r3

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


Usage: (script)
Code:

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


Custom 'setwildbattle'


along with a question
I've also developed a routine which can customize the wild pokemon for firered.
Insert this piece of code in free space:
Code:

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

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

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

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

jump_pc:
pop {pc}

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

jump_r1:
bx r1

jump_r3:
bx r3

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


How to use:
Create a script: (The usage of the variables are listed in the comment of the function written by me)
Code:

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


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

Lunos September 29th, 2015 10:07 PM

Quote:

Originally Posted by FBI (Post 8510524)

Pokemon Obedience via Level and Happiness!



How it works:
If your Pokemon outlevels the level your badges say you can control, it will disobey you if it's unhappy. The concept was pretty simple sounding, but there was a lot of work that went into it. This should keep some similarities to the anime.
I should note that if your Pokemon loves you, and you don't have the badge to train it, it will still listen to you :3

This one is called love.asm

How to insert:
Compile and insert into freespace the following code:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
    mov r4, #0x82
    lsl r4, r4, #0x4
    mov r2, #0x0

badgeLoop:
    mov r0, r4
    ldr r6, =(0x806E6D0 +1)
    bl linkerOne
    cmp r0, #0x1
    bne trainLevel
    add r4, r4, #0x1
    add r2, r2, #0x1
    cmp r2, #0x8
    beq obey
    b badgeLoop

trainLevel:
    @no flags set = lvl 20. Increment by 10 per additional flag
    mov r0, #0xA
    mov r2, #0x82
    lsl r2, r2, #0x4
    sub r4, r4, r2
    mul r4, r4, r0
    add r4, #0x14

PokemonLevel:
    ldrh r0, [r5]
    mul r0, r7
    ldr r6, = (0x2024284)
    add r0, r0, r6
    mov r1, #0x38
    ldr r6, = (0x803FBE8 +1)
    bl linkerOne
    cmp r0, r4
    ble obey

isHappy:
    @if it loves you and you don't have badges, it will obey
    @if it doesn't love you and you don't have badges it will disobey
    ldrh r0, [r5]
    mul r0, r7
    ldr r6, = (0x2024284)
    add r0, r0, r6
    mov r1, #0x20
    ldr r6, =(0x803FBE8 +1)
    bl linkerOne
    cmp r0, #0x7F @this is half possible of max happiness tone to your liking
    bls disobey

obey:
    mov r0, #0x1
    b end

disobey:
    ldr r0, =(0x801D414 +1) @you can simply mov r0 to 0x0 too
    bx r0

end:
    mov r2, #0x0
    ldr r1, =(0x801D42A +1)
    bx r1

linkerOne:
    bx r6

.align 2




Here's a compiled version:
Code:

82 24 24 01 00 22 20 1C 15 4E 00 F0 28 F8 01 28 04 D1 01 34 01 32 08 2A 1A D0 F4 E7 0A 20 82 22 12 01 A4 1A 44 43 14 34 28 88 78 43 0D 4E 80 19 38 21 0D 4E 00 F0 13 F8 A0 42 09 DD 28 88 78 43 08 4E 80 19 20 21 08 4E 00 F0 09 F8 7F 28 01 D9 01 20 01 E0 05 48 00 47 00 22 05 49 08 47 30 47 D1 E6 06 08 84 42 02 02 E9 FB 03 08 15 D4 01 08 2B D4 01 08


Navigate to 0x1D3E0 and insert:
Code:

00 48 00 47 XX XX XX 08


Where XX XX XX is the reverse hex pointer to location you compiled the routine.

I should mention there was a little bit of this routine which I'm skipping over. Basically it checks if the Pokemon is a Mew or Deoxys. It then checks if the Mew/Deoxys has it's obedience set. I find the need for this non-existent because the obedience is checked by happiness and badges my way. In the end, if you want to keep these two (rather pointless) checks, insert at 0x1D406.

Sorry for the double post. I want to keep my routines on separate posts to help in formatting the first post's index :x

Requested here: http://www.pokecommunity.com/showpost.php?p=8510180&postcount=1
I made a special exception and decided to do it for her here by that I mean no other requests were on the table:)

Hi, a completely noob in this type of scripts here.
I just wanted to know how can i properly insert this Script because i obviously don't know how and because there isn't any cheat to make the Pokemons obey xD

I tried to insert it it like this:
1) Searched for a Free Offset in FSF, in the amount of bytes typed 256
2) Went there in HxD and pasted the whole compiled script which you posted ("82 24 24 01 00 22" etc, etc)
3) Went in HxD to 1D3E0 and then typed the pointer offset from FSF
4) Saved, tried the ROM and then since the first second there was just a white screen

Once again, this is the first time i ever try to insert an ASM script in a ROM, so please, try to not kill me xD ..

EDIT:
Nvm, reading FBI's guide to insert them, wish me luck.

EDIT2:
Okay, so, i copied the whole code into the [code] tags, pasted it in a Txt file and saved it as "Love.asm" (replacing the .txt atribute)
Then, i've dropped the Love.asm to the thumb.bat and there's supposed to be a "Love.bin" file over there, which isn't :/
I'll try to compile it via CMD just like the tutorial says and see if it works that way, but in my 2nd try it didn't..

EDIT3:
Okay, trying to compile it via CMD it says:
"love.asm:0: Warning: end of file not at end of a line: newline inserted
Assembled successfully"
So.. i'll take that warning as a false alarm, i'll try to insert it in the ROM, wish me luck.

EDIT4:
Welp, didn't worked.
Opened in HxD the file "Love.bin", copied the whole thing, pasted it in an empty offset (82B31C)
Then, went to 1D3E0 and typed "00 48 00 47 1C B3 82 08"
Saved, went to a sign with a simple msgbox, typed the command "callasm 0x82B31D" just before the "end", compiled in XSE, put its offset in the sign's one at A-Map, and when i was about to test, there's just a white screen the whole time :c ...
I'm obviously doing something wrong, but a clue would be really appreciated u.u

EDIT5:
Okay, i somehow managed to insert it more correctly, but now, when i'm about to choose an attack, the game freezes ;_; ..
Is the whole thing compatible with Fire Red? xD

Blah September 30th, 2015 5:01 AM

Quote:

Originally Posted by Lunos (Post 8947935)
Hi, a completely noob in this type of scripts here.
I just wanted to know how can i properly insert this Script because i obviously don't know how and because there isn't any cheat to make the Pokemons obey xD

I tried to insert it it like this:
1) Searched for a Free Offset in FSF, in the amount of bytes typed 256
2) Went there in HxD and pasted the whole compiled script which you posted ("82 24 24 01 00 22" etc, etc)
3) Went in HxD to 1D3E0 and then typed the pointer offset from FSF
4) Saved, tried the ROM and then since the first second there was just a white screen

Once again, this is the first time i ever try to insert an ASM script in a ROM, so please, try to not kill me xD ..

EDIT:
Nvm, reading FBI's guide to insert them, wish me luck.

EDIT2:
Okay, so, i copied the whole code into the [code] tags, pasted it in a Txt file and saved it as "Love.asm" (replacing the .txt atribute)
Then, i've dropped the Love.asm to the thumb.bat and there's supposed to be a "Love.bin" file over there, which isn't :/
I'll try to compile it via CMD just like the tutorial says and see if it works that way, but in my 2nd try it didn't..

EDIT3:
Okay, trying to compile it via CMD it says:
"love.asm:0: Warning: end of file not at end of a line: newline inserted
Assembled successfully"
So.. i'll take that warning as a false alarm, i'll try to insert it in the ROM, wish me luck.

EDIT4:
Welp, didn't worked.
Opened in HxD the file "Love.bin", copied the whole thing, pasted it in an empty offset (82B31C)
Then, went to 1D3E0 and typed "00 48 00 47 1C B3 82 08"
Saved, went to a sign with a simple msgbox, typed the command "callasm 0x82B31D" just before the "end", compiled in XSE, put its offset in the sign's one at A-Map, and when i was about to test, there's just a white screen the whole time :c ...
I'm obviously doing something wrong, but a clue would be really appreciated u.u

EDIT5:
Okay, i somehow managed to insert it more correctly, but now, when i'm about to choose an attack, the game freezes ;_; ..
Is the whole thing compatible with Fire Red? xD

Mother of notifications I got from this post, lol. I think this specific routine is working, I've tested it a while ago when I was making it.

You don't use callasm, just use the compiled code snipplet, and paste it into some free space. From there you make a reverse hex pointer and place the hook at 0x1D3E0, then don't touch it, it's automated. If you're still having issues, please open your ROM in VBA -> disassemble -> (tick thumb) and in the goto space put in 0801D3D0. Print screen and paste the result in the ASM help thread or something. I'll assist with specific problems over there.

Blackhawkx164 October 1st, 2015 12:32 AM

Quote:

Originally Posted by NewDenverCity (Post 8938909)

Events that happen daily:




First of all, this uses the Day/Night System's clock, or you can use ShinyQuagsire's RTC, which I'm fairly sure are one and the same anyway. Either way, you have to have that in the game or this won't work for obvious reasons.


Insert this into free space.
Code:

.thumb
start:
 push {r0-r7, lr}
 ldr r0, =(0x20370D0)
 ldrh r1, [r0]
 mov r2, #0x4
 mul r1, r1, r2
 ldr r0, =(0x3005546)
 add r0, r0, r1
 mov r1, r0
 mov r2, r0
 add r0, #0x1
 add r1, #0x2
 add r2, #0x3
 ldrh r3, [r0]
 ldrb r4, [r1]
 ldrb r5, [r2]
 ldr r6, =(0x300553C)
 ldrh r7, [r6]
 cmp r3, r7
 bcc x800D_1
 strh r7, [r0]
 ldr r6, =(0x300553F)
 ldrb r7, [r6]
 cmp r4, r7
 bcc x800D_1
 strb r7, [r1]
 ldr r6, =(0x3005540)
 ldrb r7, [r6]
 cmp r5, r7
 bcc x800D_1
 strb r7, [r2]
 ldr r0, =(0x20370D0)
 mov r1, #0x0
 strh r1, [r0]
 pop {r0-r7, pc}
x800D_1:
 ldr r6, =(0x300553C)
 ldrh r7, [r6]
 strh r7, [r0]
 ldr r6, =(0x300553F)
 ldrb r7, [r6]
 strh r7, [r1]
 ldr r6, =(0x3005540)
 ldrb r7, [r6]
 strb r7, [r2]
 ldr r0, =(0x20370D0)
 mov r1, #0x1
 strh r1, [r0]
 pop {r0-r7, pc}


This hack uses variable x800D for almost everything. So each event that happens daily is supposed to have a number attached to it using x800D, like so.
Code:

#dynamic 0x______

#org @start
setvar 0x800D 0x_ (set 800D to the table entry.)
callasm 0x8(offset where you put my the previous ASM +1)
compare 0x800D 0x0
if 0x1 goto @1 (if x800D is the value of 0, then the event has already happened today)
compare 0x800D 0x1
if 0x1 goto @2 (if x800D is the value of 1, then the event has not happened that day)


Please credit if you use this, and report any bugs here or by PM/VM, thanks.

Hi, I have a problem with this. The timed events are all working fine until I save and reload the game. It seems once you reset the game and continue from your save that the event shows as 'not happened' despite the day being the same as when I first activated the script. I think this is a bug. Is there any workaround?

NewDenverCity October 1st, 2015 10:46 AM

Quote:

Originally Posted by Blackhawkx164 (Post 8948993)
Hi, I have a problem with this. The timed events are all working fine until I save and reload the game. It seems once you reset the game and continue from your save that the event shows as 'not happened' despite the day being the same as when I first activated the script. I think this is a bug. Is there any workaround?

I use savestates because I don't quite trust the save data fixes that other people have provided. Savestates definitely work, but I hadn't tested that with regular saves. It was an error on my part to overlook that other people would use the regular save function. If possible, I'll come up with another routine that'll do the same thing but be incorporated to the regular save data.

esperance October 2nd, 2015 1:28 PM

Reusable TMs in LeafGreen


First posted by FBI here, these routines prevent the consumption of TMs like in the recent games.

Prevent Consumption:
0x124F50: 00 00 00 00
0x125C58: 00 00 00 00
0x124E84: 00 00 00 00

Make it Ungivable:
0x132690: 00 00 17 E0

Make it Unsellable:
0x1328FC: 00 00 00 00

To remove the quantities showing up in the bag:
Code:

.text
.align 2
.thumb
.thumb_func

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

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

link:
        bx r6

.align 2


At 0x131ECC put:
00 48 00 47 XX XX XX 08
Where XX XX XX is the pointer to where you assembled the routine + 1.

Finally at 0x131E7D change the byte to E0.

esperance October 2nd, 2015 1:42 PM

Random Natural Number Generator in LeafGreen


A port of FBI's Natural RNG, this was almost exactly the same. Just needed one offset changed.

Compile and insert this routine anywhere.
Code:

text
.align 2
.thumb
.thumb_func

main:
        push {r4, lr}
        ldr r4, =(0x08044EC8 +1)@gen random number
        bl linker
        lsl r0, r0, #0x10
        lsr r0, r0, #0x10
        ldr r1, =(0x020370B8) @convert to int between 0x0 to [var 0x8000] exclusive
        ldrh r1, [r1]
        ldr r4, =(0x081E4660 +1) @ this changed
        bl linker
        ldr r1, =(0x020370D0) @store in last result
        strh r0, [r1]
        pop {r4, pc}

linker:
        bx r4

.align 2


To use it, set variable 0x8000 to the number of results you want, and it will generate a number between 0 and 0xFFFF exclusive. The result will then be placed in variable 0x8000.

robinjea October 2nd, 2015 1:46 PM

Quote:

Originally Posted by Hopeless Masquerade (Post 8951168)

Reusable TMs in LeafGreen


As part of an effort to encourage LeafGreen hacking, I've decided to begin translating various ASM routines from FireRed to LeafGreen. I decided to start with reusable TMs. First posted by FBI here, these routines prevent the consumption of TMs like in the recent games.

Prevent Consumption:
0x124F50: 00 00 00 00
0x125C58: 00 00 00 00
0x124E84: 00 00 00 00

Make it Ungivable:
0x132690: 00 00 17 E0

To remove the quantities showing up in the bag:
Code:

.text
.align 2
.thumb
.thumb_func

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

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

link:
    bx r6

.align 2


At 0x131ECC put:
00 48 00 47 XX XX XX 08
Where XX XX XX is the pointer to where you assembled the routine + 1.

Finally at 0x131E7D change the byte to E0.

Oooh~ This is cool! I remember that I chose LeafGreen above FireRed when I was a kid to be my first GBA game! Oooh~ The feels of nostalgia. T^T But you should have used and ported this one instead. It doesn't require a different routine, just a few byte edits, which I think is more practical. Just sayin'. :P

Quote:

Originally Posted by Pokemon_XY (Post 8933435)
I've found a way to make TMs unsellable:
Code:

0x132924 - 00 00 00 00


In addition, the quantity in bag when you buy TMs in the game should be hided, and here is a quick way to remove the box which shows the quantity for all items:
Code:

0x9BCC2 - 00 00 00 00


So here's the full code, no extra routines needed

Reusable TMs


Code:

0x1326BA - 17 E0 //can't hold as item
0x124F78 - 00 00 00 00 //can't delete
0x125C80 - 00 00 00 00 //can't delete
0x124EAC - 00 00 00 00 //can't delete
0x131EA6 - 2A E0 //fix the graphic
0x132924 - 00 00 00 00 //can't sell
0x9BCC2 - 00 00 00 00 //hide the box showing quantity




Touched October 2nd, 2015 1:47 PM

Quote:

Originally Posted by Hopeless Masquerade (Post 8951168)
As part of an effort to encourage LeafGreen hacking

Please don't. Thanks

esperance October 2nd, 2015 1:53 PM

Quote:

Originally Posted by Touched (Post 8951184)
Please don't. Thanks

No need to stifle creativity. Thanks.

Ephraim225 October 2nd, 2015 2:03 PM

Quote:

Originally Posted by Hopeless Masquerade (Post 8951189)
No need to stifle creativity. Thanks.

Yeah, Touched! Using Leaf Green instead of Fire Red is very creative! Why do you think Advanced Adventure is my favorite hack ever? That hack was worth the mild annoyance of being forced to go download the other version :P

Touched October 2nd, 2015 2:08 PM

Quote:

Originally Posted by Ephraim225 (Post 8951203)
Yeah, Touched! Using Leaf Green instead of Fire Red is very creative! Why do you think Advanced Adventure is my favorite hack ever? That hack was worth the mild annoyance of being forced to go download the other version :P

So if I change 24 Pokemon, edit a Tilescreen and shuffle a few functions around then label the resulting mess "WaterBlue", I'll win HOTY?

kleenexfeu October 2nd, 2015 2:14 PM

Quote:

Originally Posted by Ephraim225 (Post 8951203)
Yeah, Touched! Using Leaf Green instead of Fire Red is very creative! Why do you think Advanced Adventure is my favorite hack ever? That hack was worth the mild annoyance of being forced to go download the other version :P

I know we're already out-of-topic, sorry for that but :

What is the point of hacking LG ? It's a waste of time.

We should put all our effort together by hacking EM or FR to make more progress, there's no point on hacking LG/RUBY/SAPPHIR because they don't bring anything new/better while FR/EM have so much research done.

Please don't tell me there's nothing to hack in these games anymore. There's plenty of things to do.

Of course anyone can do whatever he wants, but for the sake of the hacking and the progress, we shouldn't encourage to hack other games than FR and EM

Blah October 2nd, 2015 2:26 PM

Meh, no one really cares. He just ported the stuff over, which is completely fine in my eyes. Lets let the folks hack what they wanna hack, sure some ROM bases are inferior, but if you don't care then whatever. I mean, all gen 3 ROMs are superior to gen 2 and 1 ROMs interms of coding and implemented features, yet people still hack those.

EDIT: I lied, early gens have complete disassembly. Sorry folks :D

RichterSnipes October 2nd, 2015 3:01 PM

Quote:

Originally Posted by Ephraim225 (Post 8951203)
Yeah, Touched! Using Leaf Green instead of Fire Red is very creative! Why do you think Advanced Adventure is my favorite hack ever?

Not to dogpile on this point, but hacking LeafGreen instead of FireRed isn't exactly that much of a revelation in most cases. If anything, most of the things done to FR can be ported to LG - including most, if not all, of the FR ASM routines in this thread - just by searching for equivalent offsets in it. If I were to create an entire game hack using FR as a base, then proceeded to port everything over to LG and release the hack just for that version, would that be considered revolutionary? Not only does it take extra effort by the hacker, it also causes an extra inconvenience to those who want to play the hack, as they'd be expecting it to be a hack of FR. The word "creative" might kind of fit in this situation, but it surely isn't convenient or intuitive.

The only reason I personally do it is because of a key principle I'm holding for the specific work I'm doing. Even then, LG support is secondary to FR for me. If I was working on a "typical" Pokémon hack based on FR/LG, I wouldn't even consider using LG for a second.

Spherical Ice October 2nd, 2015 11:51 PM

Let's not do this here. Feel free to make a thread in the ROM Hacking Hub if you wish to discuss which ROM is better.

Aruaruu October 3rd, 2015 10:09 PM

Quote:

Originally Posted by jiangzhengwenjzw (Post 8941047)

Pre-battle Mugshot Hack in BPEE


I'm trying to make elite four rematches but I can only make it show the first palette (which is in the image you posted.)
It works fine when I make a regular trainer use the mugshot but anything that uses the "elite four" trainer class just doesn't work.

Anyway you can make it work with elite four trainer class too?

jiangzhengwenjzw October 3rd, 2015 10:16 PM

Quote:

Originally Posted by Aruaruu (Post 8953342)
I'm trying to make elite four rematches but i can only make it show the first palette (which is in the image you posted.)
It works fine when I make a regular trainer use the mugshot but anything that uses the "elite four" trainer class just doesn't work.

Anyway you can make it work with elite four trainer class too?

I think that's very simple. You can see a palette pointer table at 0x5C8FDC and that's the palettes for elites and champion (first 5 entries). You can modify them by using APE (all not LZ77 compressed).
There will be boy player & girl player palette after that, but please ignore them as they're not used at all.


/*=============================================================================================================================*/


Things in the spoiler below are something need help and it may be better in the ASM help thread.
Spoiler:

Enhancement of scrolling multichoice box (special 0x158)


/*=================================================================================================*/
Actually, I've encountered a problem in hacking this special function, and it will be shown in the end of the post.
/*=================================================================================================*/
What's this:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/1_zps67abpsw8.png
The reason why I rewrote the function is that I don't want to mess up the original special function, and it's more clear for people to read it.

How to use:
Firstly we should use FBI's way to build some tables.
Quote:

Originally Posted by FBI (Post 8903237)
You need to set up a table of pointers somewhere in your ROM. This table will be a table of pointers to possible mulitchoice boxes in your ROM. Each pointer in that table will point to a location of another table. The second table will have pointers to 0xFF terminated strings which will appear in your multichoice box. Visually this is what it should look like:
Spoiler:

http://i.imgur.com/oZfTLDB.png
I suggest first setting up at least the first table before inserting the actual routine itself.

Then we need to compile and insert this useless interesting function:
Code:

.thumb
.align 2
initialize_func:
push {r4, r5, lr}
ldr r0, =0x809D6D5
ldr r1, =0x81119D5
bl call_via_r1
lsl r0, r0, #0x18
lsr r0, r0, #0x18
cmp r0, #1
beq back
mov r0, pc
add r0, #0x43
mov r1, #8
ldr r2, =0x0807741D
bl call_via_r2
lsl r0, r0, #0x18
lsr r5, r0, #0x18
lsl r0, r5, #2
add r0, r0, r5
lsl r0, r0, #3
ldr r1, =0x03005090
add r3, r0, r1
mov r2, #0
ldr r1, =0x020370B8
ldrh r0, [r1]
strh r0, [r3, #8] @row_quantity
ldrh r0, [r1, #2]
strh r0, [r3, #0xA] @option_quantity
ldrh r0, [r1, #0x12]
strh r0, [r3, #0x12] @bottom_red_arrow_Y_coordinate
ldrh r0, [r1, #4]
strh r0, [r3, #0xC] @X_coordinate
ldrh r0, [r1, #6]
strh r0, [r3, #0xE] @Y_coordinate
mov r0, #8
strh r0, [r3, #0x10]
mov r0, #0
strh r0, [r3, #0x14]
strh r5, [r3, #0x26]
ldrh r0, [r1, #8]
strh r0, [r3, #0x16]
ldrh r0, [r1, #0xA]
strh r0, [r3, #0x18]
back:
pop {r4, r5, pc}
main_func:
push {r4-r7, lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
sub sp, sp, #0x20
lsl r0, r0, #0x18
lsr r7, r0, #0x18
lsl r0, r7, #2
add r0, r0, r7
lsl r0, r0, #3
ldr r1, =0x03005090
add r5, r0, r1
ldr r1, =0x03000F28
mov r0, #1
strb r0, [r1]
ldr r0, =0x2039A18
ldr r1, =0x2039A0E
ldrh r1, [r1]
strh r1, [r0]
ldr r4, =0x2039A14
mov r1, #0xA
ldrsh r0, [r5, r1]
lsl r0, r0, #3
ldr r1, =0x8002BB1
bl call_via_r1
str r0, [r4]
ldr r2, =0x80CBA7D
bl call_via_r2
mov r6, #0
mov r4, #0
mov r2, #0xA
ldrsh r0, [r5, r2]
lsl r3, r7, #2
mov r10, r3
add r1, sp, #0x18
mov r9, r1
cmp r6, r0
bge .L_0
ldr r2, table
ldr r1, =0x020370B8
ldrh r1, [r1, #0xC]
lsl r1, r1, #0x2
add r2, r2, r1
ldr r2, [r2]
mov r8, r2
.L_1:
ldr r0, =0x2039A14
ldr r0, [r0]
lsl r3, r4, #3
add r3, r3, r0
lsl r2, r4, #2
add r2, r8
ldr r1, [r2]
str r1, [r3]
str r4, [r3, #4]
mov r0, #2
mov r2, #0
push {r4}
ldr r4, =0x8005ED5
bl call_via_r4
pop {r4}
cmp r0, r6
ble .L_2
add r6, r0, #0
.L_2:
add r0, r4, #1
lsl r0, r0, #0x18
lsr r4, r0, #0x18
mov r3, #0xA
ldrsh r0, [r5, r3]
cmp r4, r0
blt .L_1
.L_0:
mov r0, r6
add r0, #9
cmp r0, #0
bge .L_3
add r0, #7
.L_3:
asr r0, r0, #3
add r2, r0, #1
strh r2, [r5, #0x10]
mov r1, #0xC
ldrsh r0, [r5, r1]
mov r3, #0x10
ldrsh r1, [r5, r3]
add r0, r0, r1
cmp r0, #0x1D
ble .L_4
mov r0, #0x1D
sub r0, r0, r2
strh r0, [r5, #0xC]
.L_4:
ldrb r2, [r5, #0xC]
ldrb r3, [r5, #0xE]
ldr r1, =0x020370B8
ldrh r0, [r1, #0xE]
str r0, [sp] @width
ldrh r0, [r1, #0x10]
str r0, [sp, #4] @height
mov r0, #0xF
str r0, [sp, #8] @palette?
mov r0, #0x38
str r0, [sp, #0xC]
add r0, sp, #0x10
mov r1, #0
ldr r4, =0x0810FE51
bl call_via_r4
ldr r0, [sp, #0x10]
ldr r1, [sp, #0x14]
str r0, [sp, #0x18]
str r1, [sp, #0x1C]
mov r0, r9
ldr r4, =0x08003CE5
bl call_via_r4
lsl r0, r0, #0x18
lsr r0, r0, #0x18
strh r0, [r5, #0x22]
mov r1, #0
ldr r4, =0x80F7751
bl call_via_r4
ldr r4, =0x3005360
ldrh r0, [r5, #0xA]
strh r0, [r4, #0xC]
ldrh r0, [r5, #8]
strh r0, [r5, #0xE]
ldrh r0, [r5, #0x22]
strb r0, [r4, #0x10]
mov r0, r7
ldr r1, =0x80CBCC1
bl call_via_r1
ldrh r1, [r5, #0x16]
ldrh r2, [r5, #0x18]
mov r0, r4
ldr r3, =0x8106FF9
bl call_via_r3
lsl r0, r0, #0x18
lsr r0, r0, #0x18
strh r0, [r5, #0x24]
ldrh r0, [r5, #0x22]
lsl r0, r0, #0x18
lsr r0, r0, #0x18
ldr r1, =0x8003FA1
bl call_via_r1
ldrh r0, [r5, #0x22]
lsl r0, r0, #0x18
lsr r0, r0, #0x18
mov r1, #3
ldr r3, =0x8003F21
bl call_via_r3
ldr r1, =0x03005090
mov r2, r10
add r0, r2, r7
lsl r0, r0, #3
add r0, r0, r1
ldr r1, =0x80CBB29
str r1, [r0]
add sp, sp, #0x20
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7, pc}
call_via_r1:
bx r1
call_via_r2:
bx r2
call_via_r3:
bx r3
call_via_r4:
bx r4
.align 2
table: .word 0x8[offset_of_your_table]


Absolutely, we should change the table offset in the routine correspondingly.

otherwise you can use this compiled version instead:
Code:

30 B5 6D 48 6D 49 00 F0 D0 F8 00 06 00 0E 01 28
21 D0 78 46 43 30 08 21 69 4A 00 F0 C7 F8 00 06
05 0E A8 00 40 19 C0 00 66 49 43 18 00 22 66 49
08 88 18 81 48 88 58 81 48 8A 58 82 88 88 98 81
C8 88 D8 81 08 20 18 82 00 20 98 82 DD 84 08 89
D8 82 48 89 18 83 30 BD F0 B5 57 46 4E 46 45 46
E0 B4 88 B0 00 06 07 0E B8 00 C0 19 C0 00 55 49
45 18 56 49 01 20 08 70 55 48 56 49 09 88 01 80
55 4C 0A 21 68 5E C0 00 54 49 00 F0 8E F8 20 60
53 4A 00 F0 8B F8 00 26 00 24 0A 22 A8 5E BB 00
9A 46 06 A9 89 46 86 42 20 DA 42 4A 46 49 89 89
89 00 52 18 12 68 90 46 47 48 00 68 E3 00 1B 18
A2 00 42 44 11 68 19 60 5C 60 02 20 00 22 10 B4
44 4C 00 F0 6D F8 10 BC B0 42 00 DD 06 1C 60 1C
00 06 04 0E 0A 23 E8 5E 84 42 E5 DB 30 1C 09 30
00 28 00 DA 07 30 C0 10 42 1C 2A 82 0C 21 68 5E
10 23 E9 5E 40 18 1D 28 02 DD 1D 20 80 1A A8 81
2A 7B AB 7B 2C 49 C8 89 00 90 08 8A 01 90 0F 20
02 90 38 20 03 90 04 A8 00 21 2F 4C 00 F0 40 F8
04 98 05 99 06 90 07 91 48 46 2C 4C 00 F0 38 F8
00 06 00 0E 68 84 00 21 29 4C 00 F0 31 F8 29 4C
68 89 A0 81 28 89 E8 81 68 8C 20 74 38 1C 26 49
00 F0 23 F8 E9 8A 2A 8B 20 1C 24 4B 00 F0 1F F8
00 06 00 0E A8 84 68 8C 00 06 00 0E 20 49 00 F0
14 F8 68 8C 00 06 00 0E 03 21 1E 4B 00 F0 0F F8
0C 49 52 46 D0 19 C0 00 40 18 1B 49 01 60 08 B0
38 BC 98 46 A1 46 AA 46 F0 BD 08 47 10 47 18 47
20 47 C0 46 [pointer_to_your_table] D5 D6 09 08
D5 19 11 08 1D 74 07 08 90 50 00 03 B8 70 03 02
28 0F 00 03 18 9A 03 02 0E 9A 03 02 14 9A 03 02
B1 2B 00 08 7D BA 0C 08 D5 5E 00 08 51 FE 10 08
E5 3C 00 08 51 77 0F 08 60 53 00 03 C1 BC 0C 08
F9 6F 10 08 A1 3F 00 08 21 3F 00 08 29 BB 0C 08


Parameters:
Code:

0x8000: row_quantity
0x8001: option_quantity
0x8002: X_coordinate
0x8003: Y_coordinate
0x8004: start_option_No.
0x8005: arrow_position_in_current_box
0x8006: which_box_to_show?
0x8007: width
0x8008: height
0x8009:bottom_red_arrow_Y_coordinate


A script like this is required to use this hack: (I use XSE)
Code:

#org @specialhack
lock
setvar 0x8000 0x1
setvar 0x8001 0x7
setvar 0x8002 0xA
setvar 0x8003 0x5
setvar 0x8004 0x0
setvar 0x8005 0x0
setvar 0x8006 0x0
setvar 0x8007 0x8
setvar 0x8008 0x2
setvar 0x8009 0xA
callasm 0x8[offset of the function + 1]
waitstate
release
end


Yes, you're right. The problem which is apparently shown in front of you is that I failed to control "top_red_arrow_Y_coordinate". So I use an alternative way, which means that you can change variable 0x8009 to adjust the position of the bottom red arrow to make them symmetric. As the function is very easy, I hope that someone can modify this function so it will work better.

Blah October 4th, 2015 8:06 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 8953349)
stuff

What a coincidence, this morning I was making an Rbox hack myself. As for yours, the function is too complicated. You can just define most of that stuff in the routine, also use a table to avoid those variable sets, as they can get expensive/annoying if you're manually updating the box often.

What exactly are you trying to do here though?

jiangzhengwenjzw October 4th, 2015 8:23 AM

Quote:

Originally Posted by FBI (Post 8953754)
What a coincidence, this morning I was making an Rbox hack myself. As for yours, the function is too complicated. You can just define most of that stuff in the routine, also use a table to avoid those variable sets, as they can get expensive/annoying if you're manually updating the box often.

What exactly are you trying to do here though?

I'm inheriting your way to build a table for strings, and before I wrote this function I hadn't ever imagined that there will be so many parameters. :(
I want to customize this function myself because many things of the original special function can't be controlled (even coordinates, which can be controlled in "multichoice" command in script)
I think the size of the box is also important, so I've added that thing.
For this thing
Quote:

0x8004: start_option_No.
0x8005: arrow_position_in_current_box
It's really not important, as most people set them to 0 so it won't cause problem.

Anyway, could you help me solve the problem in the post?

Edit: here're something I've commented on which may make you interested:
Spoiler:
Code:

ROM:080CB844                MOVS    R0, #7          @ row_quantity
ROM:080CB846                STRH    R0, [R3,#task.args]
ROM:080CB848                MOVS    R1, #0xC
ROM:080CB84A                STRH    R1, [R3,#task.args+2] @ option_quantity
ROM:080CB84C                STRH    R4, [R3,#task.args+4] @ X
ROM:080CB84E                STRH    R4, [R3,#task.args+6] @ Y
ROM:080CB850                MOVS    R0, #8
ROM:080CB852                STRH    R0, [R3,#task.args+8]
ROM:080CB854                STRH    R1, [R3,#task.args+0xA]
ROM:080CB856                STRH    R2, [R3,#task.args+0xC]
ROM:080CB858                STRH    R5, [R3,#0x26]
ROM:080CB85A                LDR    R0, =word_2039A0E
ROM:080CB85C                LDRH    R0, [R0]        @ start_option_No.
ROM:080CB85E                STRH    R0, [R3,#0x16]
ROM:080CB860                LDR    R0, =word_2039A10
ROM:080CB862                LDRH    R0, [R0]        @ arrow_position_in_current_box
ROM:080CB864                STRH    R0, [R3,#task.args+0x10]
ROM:080CB866                B      loc_80CB8F8


Code:

ROM:080CB904                PUSH    {R4-R7,LR}
ROM:080CB906                MOV    R7, R10
ROM:080CB908                MOV    R6, R9
ROM:080CB90A                MOV    R5, R8
ROM:080CB90C                PUSH    {R5-R7}
ROM:080CB90E                SUB    SP, SP, #0x20
ROM:080CB910                LSLS    R0, R0, #0x18
ROM:080CB912                LSRS    R7, R0, #0x18
ROM:080CB914                LSLS    R0, R7, #2
ROM:080CB916                ADDS    R0, R0, R7
ROM:080CB918                LSLS    R0, R0, #3
ROM:080CB91A                LDR    R1, =tasks
ROM:080CB91C                ADDS    R5, R0, R1
ROM:080CB91E                BL      script_env_2_enable
ROM:080CB922                LDR    R0, =var_8004
ROM:080CB924                LDRH    R0, [R0]
ROM:080CB926                CMP    R0, #1
ROM:080CB928                BNE    loc_80CB944
ROM:080CB92A                LDR    R0, =word_2039A18
ROM:080CB92C                LDR    R1, =word_2039A0E
ROM:080CB92E                LDRH    R1, [R1]        @ start_option_No.
ROM:080CB930                STRH    R1, [R0]
ROM:080CB932                B      loc_80CB94A
ROM:080CB932 @ ---------------------------------------------------------------------------
ROM:080CB934 off_80CB934:    .long tasks            @ DATA XREF: sub_80CB904+16r
ROM:080CB938 off_80CB938:    .long var_8004          @ DATA XREF: sub_80CB904+1Er
ROM:080CB93C off_80CB93C:    .long word_2039A18      @ DATA XREF: sub_80CB904+26r
ROM:080CB940 off_80CB940:    .long word_2039A0E      @ DATA XREF: sub_80CB904+28r
ROM:080CB944 @ ---------------------------------------------------------------------------
ROM:080CB944
ROM:080CB944 loc_80CB944:                            @ CODE XREF: sub_80CB904+24j
ROM:080CB944                LDR    R1, =word_2039A18
ROM:080CB946                MOVS    R0, #0
ROM:080CB948                STRH    R0, [R1]
ROM:080CB94A
ROM:080CB94A loc_80CB94A:                            @ CODE XREF: sub_80CB904+2Ej
ROM:080CB94A                LDR    R4, =malloc_pointer_loc
ROM:080CB94C                MOVS    R1, #task.args+2
ROM:080CB94E                LDRSH  R0, [R5,R1]    @ option_quantity
ROM:080CB950                LSLS    R0, R0, #3
ROM:080CB952                BL      malloc_and_clear
ROM:080CB956                STR    R0, [R4]
ROM:080CB958                BL      box_properties
ROM:080CB95C                MOVS    R6, #0
ROM:080CB95E                MOVS    R4, #0
ROM:080CB960                MOVS    R2, #task.args+2
ROM:080CB962                LDRSH  R0, [R5,R2]
ROM:080CB964                LSLS    R3, R7, #2      @ task_id * 4
ROM:080CB966                MOV    R10, R3
ROM:080CB968                ADD    R1, SP, #0x40+var_28
ROM:080CB96A                MOV    R9, R1
ROM:080CB96C                CMP    R6, R0
ROM:080CB96E                BGE    loc_80CB9AE
ROM:080CB970                LDR    R2, =sp158_table
ROM:080CB972                MOV    R8, R2
ROM:080CB974
ROM:080CB974 loc_80CB974:                            @ CODE XREF: sub_80CB904+A8j
ROM:080CB974                LDR    R0, =malloc_pointer_loc
ROM:080CB976                LDR    R0, [R0]
ROM:080CB978                LSLS    R3, R4, #3
ROM:080CB97A                ADDS    R3, R3, R0
ROM:080CB97C                LSLS    R2, R4, #2
ROM:080CB97E                LDR    R0, =var_8004
ROM:080CB980                LDRH    R1, [R0]
ROM:080CB982                LSLS    R0, R1, #1
ROM:080CB984                ADDS    R0, R0, R1
ROM:080CB986                LSLS    R0, R0, #4
ROM:080CB988                ADDS    R2, R2, R0
ROM:080CB98A                ADD    R2, R8
ROM:080CB98C                LDR    R1, [R2]
ROM:080CB98E                STR    R1, [R3]
ROM:080CB990                STR    R4, [R3,#4]
ROM:080CB992                MOVS    R0, #2
ROM:080CB994                MOVS    R2, #0
ROM:080CB996                BL      font_get_width_of_string
ROM:080CB99A                CMP    R0, R6
ROM:080CB99C                BLE    loc_80CB9A0
ROM:080CB99E                ADDS    R6, R0, #0
ROM:080CB9A0
ROM:080CB9A0 loc_80CB9A0:                            @ CODE XREF: sub_80CB904+98j
ROM:080CB9A0                ADDS    R0, R4, #1
ROM:080CB9A2                LSLS    R0, R0, #0x18
ROM:080CB9A4                LSRS    R4, R0, #0x18
ROM:080CB9A6                MOVS    R3, #task.args+2
ROM:080CB9A8                LDRSH  R0, [R5,R3]
ROM:080CB9AA                CMP    R4, R0
ROM:080CB9AC                BLT    loc_80CB974
ROM:080CB9AE
ROM:080CB9AE loc_80CB9AE:                            @ CODE XREF: sub_80CB904+6Aj
ROM:080CB9AE                MOVS    R0, R6          @ width
ROM:080CB9B0                ADDS    R0, #9
ROM:080CB9B2                CMP    R0, #0
ROM:080CB9B4                BGE    loc_80CB9B8
ROM:080CB9B6                ADDS    R0, #7
ROM:080CB9B8
ROM:080CB9B8 loc_80CB9B8:                            @ CODE XREF: sub_80CB904+B0j
ROM:080CB9B8                ASRS    R0, R0, #3
ROM:080CB9BA                ADDS    R2, R0, #1
ROM:080CB9BC                STRH    R2, [R5,#task.args+8]
ROM:080CB9BE                MOVS    R1, #task.args+4
ROM:080CB9C0                LDRSH  R0, [R5,R1]
ROM:080CB9C2                MOVS    R3, #task.args+8
ROM:080CB9C4                LDRSH  R1, [R5,R3]
ROM:080CB9C6                ADDS    R0, R0, R1
ROM:080CB9C8                CMP    R0, #0x1D
ROM:080CB9CA                BLE    loc_80CB9D2
ROM:080CB9CC                MOVS    R0, #0x1D
ROM:080CB9CE                SUBS    R0, R0, R2
ROM:080CB9D0                STRH    R0, [R5,#task.args+4]
ROM:080CB9D2
ROM:080CB9D2 loc_80CB9D2:                            @ CODE XREF: sub_80CB904+C6j
ROM:080CB9D2                LDRB    R2, [R5,#task.args+4] @ X
ROM:080CB9D4                LDRB    R3, [R5,#task.args+6] @ Y
ROM:080CB9D6                LDRB    R0, [R5,#task.args+8]
ROM:080CB9D8                STR    R0, [SP,#0x40+var_40] @ width
ROM:080CB9DA                LDRB    R0, [R5,#task.args+0xA]
ROM:080CB9DC                STR    R0, [SP,#0x40+var_3C] @ height
ROM:080CB9DE                MOVS    R0, #0xF
ROM:080CB9E0                STR    R0, [SP,#0x40+var_38] @ color
ROM:080CB9E2                MOVS    R0, #0x38 @ '8'
ROM:080CB9E4                STR    R0, [SP,#0x40+var_34]
ROM:080CB9E6                ADD    R0, SP, #0x40+var_30
ROM:080CB9E8                MOVS    R1, #0
ROM:080CB9EA                BL      draw_interior
ROM:080CB9EE                LDR    R0, [SP,#0x40+var_30]
ROM:080CB9F0                LDR    R1, [SP,#0x40+var_2C]
ROM:080CB9F2                STR    R0, [SP,#0x40+var_28]
ROM:080CB9F4                STR    R1, [SP,#0x40+var_24]
ROM:080CB9F6                MOV    R0, R9
ROM:080CB9F8                BL      rbox_08003CE4
ROM:080CB9FC                LSLS    R0, R0, #0x18
ROM:080CB9FE                LSRS    R0, R0, #0x18
ROM:080CBA00                STRH    R0, [R5,#0x22]  @ rboxid
ROM:080CBA02                MOVS    R1, #0
ROM:080CBA04                BL      rboxid_draw_border
ROM:080CBA08                LDR    R4, =dword_3005360
ROM:080CBA0A                LDRH    R0, [R5,#task.args+2]
ROM:080CBA0C                STRH    R0, [R4,#(word_300536C - dword_3005360)] @ option_quantity
ROM:080CBA0E                LDRH    R0, [R5,#task.args]
ROM:080CBA10                STRH    R0, [R4,#(word_300536E - dword_3005360)] @ row_quantity
ROM:080CBA12                LDRH    R0, [R5,#0x22]
ROM:080CBA14                STRB    R0, [R4,#(byte_3005370 - dword_3005360)] @ rboxid
ROM:080CBA16                MOVS    R0, R7          @ task_id
ROM:080CBA18                BL      draw_red_arrow
ROM:080CBA1C                LDRH    R1, [R5,#0x16]  @ start_option_No.
ROM:080CBA1E                LDRH    R2, [R5,#task.args+0x10] @ arrow_position_in_current_box
ROM:080CBA20                MOVS    R0, R4
ROM:080CBA22                BL      sub_8106FF8
ROM:080CBA26                LSLS    R0, R0, #0x18
ROM:080CBA28                LSRS    R0, R0, #0x18
ROM:080CBA2A                STRH    R0, [R5,#0x24]
ROM:080CBA2C                LDRH    R0, [R5,#0x22]
ROM:080CBA2E                LSLS    R0, R0, #0x18
ROM:080CBA30                LSRS    R0, R0, #0x18
ROM:080CBA32                BL      rboxid_8003FA0
ROM:080CBA36                LDRH    R0, [R5,#0x22]
ROM:080CBA38                LSLS    R0, R0, #0x18
ROM:080CBA3A                LSRS    R0, R0, #0x18
ROM:080CBA3C                MOVS    R1, #3
ROM:080CBA3E                BL      rboxid_to_vram
ROM:080CBA42                LDR    R1, =tasks
ROM:080CBA44                MOV    R2, R10
ROM:080CBA46                ADDS    R0, R2, R7
ROM:080CBA48                LSLS    R0, R0, #3
ROM:080CBA4A                ADDS    R0, R0, R1
ROM:080CBA4C                LDR    R1, =(sub_80CBB28+1)
ROM:080CBA4E                STR    R1, [R0]
ROM:080CBA50                ADD    SP, SP, #0x20
ROM:080CBA52                POP    {R3-R5}
ROM:080CBA54                MOV    R8, R3
ROM:080CBA56                MOV    R9, R4
ROM:080CBA58                MOV    R10, R5
ROM:080CBA5A                POP    {R4-R7}
ROM:080CBA5C                POP    {R0}
ROM:080CBA5E                BX      R0
ROM:080CBA5E @ End of function sub_80CB904
ROM:080CBA5E
ROM:080CBA5E @ ---------------------------------------------------------------------------
ROM:080CBA60 off_80CBA60:    .long word_2039A18      @ DATA XREF: sub_80CB904:loc_80CB944r
ROM:080CBA64 off_80CBA64:    .long malloc_pointer_loc @ DATA XREF: sub_80CB904:loc_80CB94Ar
ROM:080CBA64                                        @ sub_80CB904:loc_80CB974r
ROM:080CBA68 off_80CBA68:    .long sp158_table      @ DATA XREF: sub_80CB904+6Cr
ROM:080CBA6C off_80CBA6C:    .long var_8004          @ DATA XREF: sub_80CB904+7Ar
ROM:080CBA70 off_80CBA70:    .long dword_3005360    @ DATA XREF: sub_80CB904+104r
ROM:080CBA74 off_80CBA74:    .long tasks            @ DATA XREF: sub_80CB904+13Er
ROM:080CBA78 off_80CBA78:    .long sub_80CBB28+1    @ DATA XREF: sub_80CB904+148r




Another thing: would you mind modifying (or deleting) the quote part in your reply to me, as it's quite long and I've placed it in a spoiler.

Lance32497 October 6th, 2015 2:10 AM

Quote:

Originally Posted by avantimaestro (Post 8919240)
Temporarily disabling prize money from battle

(Only works in FireRed)

Here is a routine that will prevent you from getting money after you won a battle against a trainer. Good for tournament-style battles, where it makes no sense that you get or lose money.

How to insert:

Compile and insert this routine anywhere 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, #0x5
    ldr r2, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r2, =(0x809FDA0 +1)
    bl linker
    ldr r1, =(0x8025A00 +1)
    bx r1

skip:
    pop {r0-r3}
    mov r0, #0x0
    mov r1, r8
    ldr r0, [r1]
    mov r1, #0xa4
    lsl r1, r1, #0x2
    add r0, r0, r1
    add r1, r4, #0x0
    ldr r1, =(0x8025A00 +1)
    bx r1

linker:
    bx r2

.align 2


(not really space saving, i know...)

Compiled:
Code:

0F B4 FF 20 40 00 05 30 0E 4A 00 F0 19 F8 01 28 0C D0 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 09 4A 00 F0 0C F8 08 49 08 47 0F BC 00 20 41 46 08 68 A4 21 89 00 40 18 21 1C 03 49 08 47 10 47 C0 46 D1 E6 06 08 A1 FD 09 08 01 5A 02 08



Now navigate to 0x0259E8 and insert following bytes:
Code:

00 48 00 47 XX XX XX 08


Where XX XX XX is the location of the routine you inserted + 1.


Next compile and insert this routine into free space:
Spoiler:
Code:

.text
.align 2
.thumb
.thumb_func

main:
    mov r0, #0xFF
    lsl r0, r0, #0x1
    add r0, r0, #0x5
    ldr r2, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip
    add r0, r4, #0x0
    ldr r2, =(0x809fdd8 +1)
    bl linker

skip:
    ldr r2, =(0x80a0058 +1)
    bl linker
    ldr r2, =(0x8054BEA +1)

linker:
    bx r2

.align 2


Compiled:
Code:

FF 20 40 00 05 30 07 4A 00 F0 0A F8 01 28 03 D0 20 1C 05 4A 00 F0 04 F8 04 4A 00 F0 01 F8 04 4A 10 47 C0 46 D1 E6 06 08 D9 FD 09 08 59 00 0A 08 EB 4B 05 08



Finally navigate to 0x054BE0 and insert following bytes where XX XX XX is the location of the second routine +1:
Code:

00 48 00 47 XX XX XX 08


This thing requires two routines, that's because the money gets reduced when you black out while the prize money is gained after the message appears. These are two different places so there have to be two different functions :P


At last you should also want to remove the text that appears after winning/losing that informs you about the money you gained/lost. You need another routine for that. Compile and insert into free space:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

main:
    ldr r0, =(0x83fb432)
    cmp r2, r0
    beq checkflag
    ldr r0, =(0x83fb4f6)
    cmp r2, r0
    beq checkflag
    b noskip

checkflag:
    mov r0, #0xFF
    lsl r0, r0, #0x1
    add r0, r0, #0x5
    ldr r3, =(0x806E6D0 +1)
    bl linker
    cmp r0, #0x1
    beq skip

noskip:
    ldr r0, =(0x202298C)
    mov r1, #0x0
    ldr r3, =(0x80D87BC +1)
    bl linker

skip:
    ldr r0, =(0x8032B4C +1)
    bx r0

linker:
    bx r3

.align 2


Compiled:
Code:

0B 48 82 42 03 D0 0B 48 82 42 00 D0 07 E0 FF 20 40 00 05 30 08 4B 00 F0 09 F8 01 28 04 D0 07 48 00 21 07 4B 00 F0 02 F8 06 48 00 47 18 47 C0 46 32 B4 3F 08 F6 B4 3F 08 D1 E6 06 08 8C 29 02 02 BD 87 0D 08 4D 2B 03 08



Now change the bytes at 0x032B44 to following (XX XX XX) is the location of this last routine:
Code:

00 48 00 47 XX XX XX 08


How to use:

In order to disable prize money you have to set the flag 0x203.
If you want to reenable it just clear the flag and you will get money again.

WOW! You're great thanks man!

pokefreak890 October 6th, 2015 10:45 AM

okay so the upgraded sturdy worked and now im trying to do no guard so i got to the point where i had to insert 00 49 08 47 xx xx xx 08 00 00 at 046754 and i did that and my offset is A0A1A8 but i did it reverse so it should be A9A1A0 so when i test it i miss but when i put 00 instead of 08 i dont miss but the game freezes plz help

jiangzhengwenjzw October 13th, 2015 5:13 AM

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.)
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/Untitled_zpsj3bd633m.gif
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


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]


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

Lance32497 October 13th, 2015 3:06 PM

Quote:

Originally Posted by FBI (Post 8903237)

Scrolling Multi-choice boxes



Multiple choice boxes have been a really cool, yet in my opinion, a very unmastered feature in ROM hacks. Most people use JPAN's patch to make multichoice boxes, others edit the existing ones in the ROM. However, it seems like there is no solution for when the multiple choice box needs to hold more than just 8 or so options. Most competent hackers seem to have the last option be something which opens another box. It seems clunky and quite troublesome, so I decided to hack it and make it support scrolling and customization :)

Here are some things which are in some popular hacks which use a work around that can be avoided altogether with this hack:
http://i35.photobucket.com/albums/d178/prossy/20.pnghttp://i.imgur.com/7xjCAol.pnghttp://i.imgur.com/CnolW43.png

The hack in action:



How to insert:

Before getting started with the hack there is a little bit of setting up which is required.

You need to set up a table of pointers somewhere in your ROM. This table will be a table of pointers to possible mulitchoice boxes in your ROM. Each pointer in that table will point to a location of another table. The second table will have pointers to 0xFF terminated strings which will appear in your multichoice box. Visually this is what it should look like:
Spoiler:

http://i.imgur.com/oZfTLDB.png
I suggest first setting up atleast the first table before inserting the actual routine itself.


Once you've configured the above tables, take a look at the routine in the spoilers.
Code:

table:
        .word 0x8[Location of your table, do not +1]


Change this line according to wherever you put your first table.

Once that's done compile and insert the routine into free word-aligned space!

Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func

@hook via r1

main:
        ldr r4, =(0x20370BA) @var 0x8001
        ldrh r4, [r4]
        mov r1, #0xA
        strh r4, [r5, r1]
        ldrsh r0, [r5, r1]
        lsl r0, r0, #0x3
        ldr r2, malloc
        bl linker
        ldr r4, =(0x2039A14) @RAM to hold pointer to malloc data
        str r0, [r4]
        ldr r2, boxProperties
        bl linker
        mov r6, #0x0
        mov r4, #0x0
        mov r2, #0xA
        ldrsh r0, [r5, r2]
        lsl r3, r7, #0x2
        mov r10, r3
        add r1, SP, #0x18
        mov r9, r1
        cmp r6, r0
        bge loop
        ldr r2, table
        ldr r1, =(0x20370B8) @var 0x8000
        ldrh r1, [r1]
        lsl r1, r1, #0x2
        add r2, r2, r1
        ldr r2, [r2]
        mov r8, r2
        ldr r0, =(0x80CB974 +1)
        bx r0

loop:
        ldr r0, =(0x80CB9AE +1)
        bx r0

linker:
        bx r2

.align 2

table:
        .word 0x8[Location of your table, do not +1]

malloc:
        .word 0x8002BB0 +1

boxProperties:
        .word 0x80CBA7C +1




Now navigate to 080CB94C and insert the following byte changes:
Code:

00 49 08 47 XX XX XX 08


Where XX XX XX is wherever you inserted this routine +1. Note that the trailing 08 may change depending on your ROM situation!


Usage:

So this is a hack of special 0x158. I've essentially fixed the hard coded table read, and removed limitters as well as recoded the size readings to read of a variable instead. So the script usage of this implementation is quite simple, yet there are some complications which arise along the way. I'll talk about those complications later and first describe usage!

Code:

Paramaters:
var 0x8000 = which multichoice box should be shown from the table of multichoice boxes
var 0x8001 = How many options are supposed to be shown
var 0x8004 = leave as 0x0 for expected output. It does more, but don't play with it for now (I'll document it on a later day!).

Return value:
var 0x800D = Which option was selected, where 0x0 is the first option and 0x1 is the second options....ect.


Sample script snipplet.
Code:

#dyn 0x740000
#org @start
lock
faceplayer
msgbox 0x874001B
callstd MSG_NORMAL
setvar 0x8000 0x0 'Use first multichoice box
setvar 0x8001 0x12 ' First box has 18 options
setvar 0x8004 0x0 ' standard
special 0x158
waitspecial
release
end

#org 0x874001B
= Hello here's some tough choices


Note, after the waitspecial command finishes, variable 0x800D will have the selected option's index number inside it. From there you can do your own checks to verify which option the user had selected.

Some usage requirements:

- 0x8004 = 0. Keep it like this for now until I explain it more a later day. You can play with it too if you want, but it will likely cause a game crash.

- The menu does not close unless the "B" button is pressed inplace of an option, OR the last option is selected. FR counters this by having an "EXIT" option as the last option of the multichoice box, and any scripts which use the multichoice box are looped as well. I have a fix for this:
Code:

@ 080CBB84 insert the following byte changes:
@ 00 00 00 00


So use this if you don't want to use the last option EXIT :)

This is, indeed, an awesome hack and I had implemented it so great thanks FBI, but, I have a little suggestion about this hack, I don't know if it can be implemented by setting value in a certain var or whatever, it would be cool if we can set or change the Xpos and Ypos of the multibox and extend the height of it.

jiangzhengwenjzw October 13th, 2015 3:43 PM

Quote:

Originally Posted by Lance32497 (Post 8964596)
This is, indeed, an awesome hack and I had implemented it so great thanks FBI, but, I have a little suggestion about this hack, I don't know if it can be implemented by setting value in a certain var or whatever, it would be cool if we can set or change the Xpos and Ypos of the multibox and extend the height of it.

I've done some features in this post

Lance32497 October 14th, 2015 5:46 PM

Quote:

Originally Posted by jiangzhengwenjzw (Post 8964629)
I've done some features in this post

Oh. I didn't notice it, cool

Xencleamas October 17th, 2015 11:32 PM

I dunno if someone already done this before, but... can I request for a routine that disables the registering of Pokemon into Pokedex, both Seen and Caught? It is just like when you encounter some such species in Battle Frontier/Subway/Maison, and PWT, then it will not register to Pokedex.

mkarthick98 October 18th, 2015 11:15 PM

Since people will be coming up with Mega Evolution hacks soon, I was wondering if there is a way to store all 40+ Mega stones in the bag. Would it be possible to hack the TM case and make something like a 'Mega Stone case', which can hold these stones?

azurile13 October 19th, 2015 1:49 AM

Quote:

Originally Posted by mkarthick98 (Post 8970596)
Since people will be coming up with Mega Evolution hacks soon, I was wondering if there is a way to store all 40+ Mega stones in the bag. Would it be possible to hack the TM case and make something like a 'Mega Stone case', which can hold these stones?

I don't know the logistics of essentially creating a brand new pocket, but it isn't really necessary. You can just expand the regular items pocket. The bigger cost is finding 4 bytes for each unique item. I personally used JPAN's save research (not the "save block hack").

jirachiwishmaker October 24th, 2015 9:01 PM

Could I require a routine which can let the multiple Pokemon roaming at once in Emerald by using its original engine like the same as Gold/ Silver version? Thank you very much in advance.

Lunos October 30th, 2015 7:38 AM

Hi Guys.
I wanted to know if it would be somehow possible an ASM Routine to change the Main Character Overworld permanently, until you trigger another ASM which reverts that.

Example:
Item 1: Calls the 1st ASM which would change your Overworld permanently for another one, the main girl character for example.

Item 2: Reverts what the first item did by triggering a 2nd asm.

Would that be possible?
I've just learned some hours ago, how to trigger a script through an item and the single idea of having clothes as Key Items sounds wonderful <3

But the method with the Write Bytes to Offset is kinda "Meh", because it disappear when you refresh the map or use a warp, and it would be very annoying to put the whole WBtO thing in every single warp of the game >_< ..

Lance32497 October 30th, 2015 2:23 PM

Quote:

Originally Posted by Lunos (Post 8980904)
Hi Guys.
I wanted to know if it would be somehow possible an ASM Routine to change the Main Character Overworld permanently, until you trigger another ASM which reverts that.

Example:
Item 1: Calls the 1st ASM which would change your Overworld permanently for another one, the main girl character for example.

Item 2: Reverts what the first item did by triggering a 2nd asm.

Would that be possible?
I've just learned some hours ago, how to trigger a script through an item and the single idea of having clothes as Key Items sounds wonderful <3

But the method with the Write Bytes to Offset is kinda "Meh", because it disappear when you refresh the map or use a warp, and it would be very annoying to put the whole WBtO thing in every single warp of the game >_< ..

one of JPAN Routine does that

Lunos October 31st, 2015 4:23 AM

Quote:

Originally Posted by azurile13 (Post 8970660)
I don't know the logistics of essentially creating a brand new pocket, but it isn't really necessary. You can just expand the regular items pocket. The bigger cost is finding 4 bytes for each unique item. I personally used JPAN's save research (not the "save block hack").

4 Bytes for more than 50 items, gg well played.
A brand new pocket TM Case like sounds way too more organized.

ON:
My previous question still stands since i wasn't able to find JPAN's routine xD

Touched October 31st, 2015 4:39 AM

Quote:

Originally Posted by Lunos (Post 8980904)
Hi Guys.
I wanted to know if it would be somehow possible an ASM Routine to change the Main Character Overworld permanently, until you trigger another ASM which reverts that.

Example:
Item 1: Calls the 1st ASM which would change your Overworld permanently for another one, the main girl character for example.

Item 2: Reverts what the first item did by triggering a 2nd asm.

Would that be possible?
I've just learned some hours ago, how to trigger a script through an item and the single idea of having clothes as Key Items sounds wonderful <3

But the method with the Write Bytes to Offset is kinda "Meh", because it disappear when you refresh the map or use a warp, and it would be very annoying to put the whole WBtO thing in every single warp of the game >_< ..

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

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



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.

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.

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 r3, saveblock1_mapdata
        ldr r3, [r3]
        ldrb r0, [r4]        @ person/local ID from var 0x8000
        ldrb r1, [r3, #5] @ current map
        ldrb r2, [r3, #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



Spherical Ice October 31st, 2015 8:49 AM

Quote:

Originally Posted by FBI (Post 8512782)
I don't know where it is either. Perhaps you can ask daniilS via VM or something.




1) For forced evolution, I don't know what you're really talking about. You mean just make a Pokemon evolve without giving the player time to hit the "b" button? I'll look into Pokemon evolution sure.

2) I haven't seen it so VMing me it would be nice. Anyways this is rather easy, I've done it before. I'll post the results at the bottom of this post.

3) Skipping the introduction was already done by Knizz. There's a post in the research and development section's quick research thread.


Preventing TMs from being consumed on use



Quick research:
TMs are deleted in two places. The first place is in their own function. When called from the bag, after use the TM has it's own deletion mechanism. The second way is from the bag, after you use a TM the bag attempts to delete it as well. Well, the solution is quite simple. There's two ways to do this, either go to 0809A1D8 call your own function there which checks if the item is a TM, and if it is, just jump to the end. Or much more simply you just remove the parts from the bag and tm function that deletes the TM (Which is what I did). The former way is a way you can make another item you have unconsumable.

To insert:
Do the byte changes below
0x124F78: 00 00 00 00
0x125C80: 00 00 00 00

Make it Ungivable:
insert that at 0x1326B8: 00 00 17 E0

Make it consumable after animation:
Insert: 00 00 00 00 at 0x124F78

To remove the quantities showing up in the bag:

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




Here's a compiled version:
Code:

00 2D 01 D1 05 4B 18 47 38 1C 08 21 22 1C 04 4E 00 F0 02 F8 01 4B 18 47 30 47 C0 46 FF 1E 13 08 B1 35 13 08


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

Unsellable:
Basically for the TMs, you can still sell them to vendors. To change this, you need to modify each TM individually. It's unfortunate, but the game checks if an item can be sold my comparing it's market price to zero. If it's strictly greater than zero, then you can sell it to a vendor, seems to be the rule. So to make TMs unsellable you need to set their market prices individually to zero.
I can't use my own checks to disguise the TMs as unique because the sell routine in shops are used for ALL items including potions, berries, TMs, and other items like nuggets.


Present :3
http://i.imgur.com/3nina1p.png?1

To make TMs ungivable when chosen through the Pokémon -> Give menu, navigate to 0x13288D and change the byte to E0.

Lance32497 October 31st, 2015 3:42 PM

Quote:

Originally Posted by jiangzhengwenjzw (Post 8953349)
I think that's very simple. You can see a palette pointer table at 0x5C8FDC and that's the palettes for elites and champion (first 5 entries). You can modify them by using APE (all not LZ77 compressed).
There will be boy player & girl player palette after that, but please ignore them as they're not used at all.


/*=============================================================================================================================*/


Things in the spoiler below are something need help and it may be better in the ASM help thread.
Spoiler:

Enhancement of scrolling multichoice box (special 0x158)


/*=================================================================================================*/
Actually, I've encountered a problem in hacking this special function, and it will be shown in the end of the post.
/*=================================================================================================*/
What's this:
http://i869.photobucket.com/albums/ab256/jiangzhengwenjz/1_zps67abpsw8.png
The reason why I rewrote the function is that I don't want to mess up the original special function, and it's more clear for people to read it.

How to use:
Firstly we should use FBI's way to build some tables.


Then we need to compile and insert this useless interesting function:
Code:

.thumb
.align 2
initialize_func:
push {r4, r5, lr}
ldr r0, =0x809D6D5
ldr r1, =0x81119D5
bl call_via_r1
lsl r0, r0, #0x18
lsr r0, r0, #0x18
cmp r0, #1
beq back
mov r0, pc
add r0, #0x43
mov r1, #8
ldr r2, =0x0807741D
bl call_via_r2
lsl r0, r0, #0x18
lsr r5, r0, #0x18
lsl r0, r5, #2
add r0, r0, r5
lsl r0, r0, #3
ldr r1, =0x03005090
add r3, r0, r1
mov r2, #0
ldr r1, =0x020370B8
ldrh r0, [r1]
strh r0, [r3, #8] @row_quantity
ldrh r0, [r1, #2]
strh r0, [r3, #0xA] @option_quantity
ldrh r0, [r1, #0x12]
strh r0, [r3, #0x12] @bottom_red_arrow_Y_coordinate
ldrh r0, [r1, #4]
strh r0, [r3, #0xC] @X_coordinate
ldrh r0, [r1, #6]
strh r0, [r3, #0xE] @Y_coordinate
mov r0, #8
strh r0, [r3, #0x10]
mov r0, #0
strh r0, [r3, #0x14]
strh r5, [r3, #0x26]
ldrh r0, [r1, #8]
strh r0, [r3, #0x16]
ldrh r0, [r1, #0xA]
strh r0, [r3, #0x18]
back:
pop {r4, r5, pc}
main_func:
push {r4-r7, lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
sub sp, sp, #0x20
lsl r0, r0, #0x18
lsr r7, r0, #0x18
lsl r0, r7, #2
add r0, r0, r7
lsl r0, r0, #3
ldr r1, =0x03005090
add r5, r0, r1
ldr r1, =0x03000F28
mov r0, #1
strb r0, [r1]
ldr r0, =0x2039A18
ldr r1, =0x2039A0E
ldrh r1, [r1]
strh r1, [r0]
ldr r4, =0x2039A14
mov r1, #0xA
ldrsh r0, [r5, r1]
lsl r0, r0, #3
ldr r1, =0x8002BB1
bl call_via_r1
str r0, [r4]
ldr r2, =0x80CBA7D
bl call_via_r2
mov r6, #0
mov r4, #0
mov r2, #0xA
ldrsh r0, [r5, r2]
lsl r3, r7, #2
mov r10, r3
add r1, sp, #0x18
mov r9, r1
cmp r6, r0
bge .L_0
ldr r2, table
ldr r1, =0x020370B8
ldrh r1, [r1, #0xC]
lsl r1, r1, #0x2
add r2, r2, r1
ldr r2, [r2]
mov r8, r2
.L_1:
ldr r0, =0x2039A14
ldr r0, [r0]
lsl r3, r4, #3
add r3, r3, r0
lsl r2, r4, #2
add r2, r8
ldr r1, [r2]
str r1, [r3]
str r4, [r3, #4]
mov r0, #2
mov r2, #0
push {r4}
ldr r4, =0x8005ED5
bl call_via_r4
pop {r4}
cmp r0, r6
ble .L_2
add r6, r0, #0
.L_2:
add r0, r4, #1
lsl r0, r0, #0x18
lsr r4, r0, #0x18
mov r3, #0xA
ldrsh r0, [r5, r3]
cmp r4, r0
blt .L_1
.L_0:
mov r0, r6
add r0, #9
cmp r0, #0
bge .L_3
add r0, #7
.L_3:
asr r0, r0, #3
add r2, r0, #1
strh r2, [r5, #0x10]
mov r1, #0xC
ldrsh r0, [r5, r1]
mov r3, #0x10
ldrsh r1, [r5, r3]
add r0, r0, r1
cmp r0, #0x1D
ble .L_4
mov r0, #0x1D
sub r0, r0, r2
strh r0, [r5, #0xC]
.L_4:
ldrb r2, [r5, #0xC]
ldrb r3, [r5, #0xE]
ldr r1, =0x020370B8
ldrh r0, [r1, #0xE]
str r0, [sp] @width
ldrh r0, [r1, #0x10]
str r0, [sp, #4] @height
mov r0, #0xF
str r0, [sp, #8] @palette?
mov r0, #0x38
str r0, [sp, #0xC]
add r0, sp, #0x10
mov r1, #0
ldr r4, =0x0810FE51
bl call_via_r4
ldr r0, [sp, #0x10]
ldr r1, [sp, #0x14]
str r0, [sp, #0x18]
str r1, [sp, #0x1C]
mov r0, r9
ldr r4, =0x08003CE5
bl call_via_r4
lsl r0, r0, #0x18
lsr r0, r0, #0x18
strh r0, [r5, #0x22]
mov r1, #0
ldr r4, =0x80F7751
bl call_via_r4
ldr r4, =0x3005360
ldrh r0, [r5, #0xA]
strh r0, [r4, #0xC]
ldrh r0, [r5, #8]
strh r0, [r5, #0xE]
ldrh r0, [r5, #0x22]
strb r0, [r4, #0x10]
mov r0, r7
ldr r1, =0x80CBCC1
bl call_via_r1
ldrh r1, [r5, #0x16]
ldrh r2, [r5, #0x18]
mov r0, r4
ldr r3, =0x8106FF9
bl call_via_r3
lsl r0, r0, #0x18
lsr r0, r0, #0x18
strh r0, [r5, #0x24]
ldrh r0, [r5, #0x22]
lsl r0, r0, #0x18
lsr r0, r0, #0x18
ldr r1, =0x8003FA1
bl call_via_r1
ldrh r0, [r5, #0x22]
lsl r0, r0, #0x18
lsr r0, r0, #0x18
mov r1, #3
ldr r3, =0x8003F21
bl call_via_r3
ldr r1, =0x03005090
mov r2, r10
add r0, r2, r7
lsl r0, r0, #3
add r0, r0, r1
ldr r1, =0x80CBB29
str r1, [r0]
add sp, sp, #0x20
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7, pc}
call_via_r1:
bx r1
call_via_r2:
bx r2
call_via_r3:
bx r3
call_via_r4:
bx r4
.align 2
table: .word 0x8[offset_of_your_table]


Absolutely, we should change the table offset in the routine correspondingly.

otherwise you can use this compiled version instead:
Code:

30 B5 6D 48 6D 49 00 F0 D0 F8 00 06 00 0E 01 28
21 D0 78 46 43 30 08 21 69 4A 00 F0 C7 F8 00 06
05 0E A8 00 40 19 C0 00 66 49 43 18 00 22 66 49
08 88 18 81 48 88 58 81 48 8A 58 82 88 88 98 81
C8 88 D8 81 08 20 18 82 00 20 98 82 DD 84 08 89
D8 82 48 89 18 83 30 BD F0 B5 57 46 4E 46 45 46
E0 B4 88 B0 00 06 07 0E B8 00 C0 19 C0 00 55 49
45 18 56 49 01 20 08 70 55 48 56 49 09 88 01 80
55 4C 0A 21 68 5E C0 00 54 49 00 F0 8E F8 20 60
53 4A 00 F0 8B F8 00 26 00 24 0A 22 A8 5E BB 00
9A 46 06 A9 89 46 86 42 20 DA 42 4A 46 49 89 89
89 00 52 18 12 68 90 46 47 48 00 68 E3 00 1B 18
A2 00 42 44 11 68 19 60 5C 60 02 20 00 22 10 B4
44 4C 00 F0 6D F8 10 BC B0 42 00 DD 06 1C 60 1C
00 06 04 0E 0A 23 E8 5E 84 42 E5 DB 30 1C 09 30
00 28 00 DA 07 30 C0 10 42 1C 2A 82 0C 21 68 5E
10 23 E9 5E 40 18 1D 28 02 DD 1D 20 80 1A A8 81
2A 7B AB 7B 2C 49 C8 89 00 90 08 8A 01 90 0F 20
02 90 38 20 03 90 04 A8 00 21 2F 4C 00 F0 40 F8
04 98 05 99 06 90 07 91 48 46 2C 4C 00 F0 38 F8
00 06 00 0E 68 84 00 21 29 4C 00 F0 31 F8 29 4C
68 89 A0 81 28 89 E8 81 68 8C 20 74 38 1C 26 49
00 F0 23 F8 E9 8A 2A 8B 20 1C 24 4B 00 F0 1F F8
00 06 00 0E A8 84 68 8C 00 06 00 0E 20 49 00 F0
14 F8 68 8C 00 06 00 0E 03 21 1E 4B 00 F0 0F F8
0C 49 52 46 D0 19 C0 00 40 18 1B 49 01 60 08 B0
38 BC 98 46 A1 46 AA 46 F0 BD 08 47 10 47 18 47
20 47 C0 46 [pointer_to_your_table] D5 D6 09 08
D5 19 11 08 1D 74 07 08 90 50 00 03 B8 70 03 02
28 0F 00 03 18 9A 03 02 0E 9A 03 02 14 9A 03 02
B1 2B 00 08 7D BA 0C 08 D5 5E 00 08 51 FE 10 08
E5 3C 00 08 51 77 0F 08 60 53 00 03 C1 BC 0C 08
F9 6F 10 08 A1 3F 00 08 21 3F 00 08 29 BB 0C 08


Parameters:
Code:

0x8000: row_quantity
0x8001: option_quantity
0x8002: X_coordinate
0x8003: Y_coordinate
0x8004: start_option_No.
0x8005: arrow_position_in_current_box
0x8006: which_box_to_show?
0x8007: width
0x8008: height
0x8009:bottom_red_arrow_Y_coordinate


A script like this is required to use this hack: (I use XSE)
Code:

#org @specialhack
lock
setvar 0x8000 0x1
setvar 0x8001 0x7
setvar 0x8002 0xA
setvar 0x8003 0x5
setvar 0x8004 0x0
setvar 0x8005 0x0
setvar 0x8006 0x0
setvar 0x8007 0x8
setvar 0x8008 0x2
setvar 0x8009 0xA
callasm 0x8[offset of the function + 1]
waitstate
release
end


Yes, you're right. The problem which is apparently shown in front of you is that I failed to control "top_red_arrow_Y_coordinate". So I use an alternative way, which means that you can change variable 0x8009 to adjust the position of the bottom red arrow to make them symmetric. As the function is very easy, I hope that someone can modify this function so it will work better.

I dunno why it happens, how will I show the other choices?


this is the script that I made
Spoiler:

#org 0x8ECED1
lock
setvar 0x8000 0xA
setvar 0x8001 0xA
setvar 0x8002 0x20
setvar 0x8003 0x1
setvar 0x8004 0x0
setvar 0x8005 0x0
setvar 0x8006 0x0
setvar 0x8007 0x8
setvar 0x8008 0xF
setvar 0x8009 0xF
callasm 0x9800001
waitstate
release
end

Trainer 781 November 4th, 2015 6:26 AM

Battle End Move Target Held Items (FR):-

Loader Routine:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global targetitemloader

CheckOutcome:
      ldr r1, .Outcome
      ldrb r0, [r1]
      mov r1, #0x29
      and r0, r1
      cmp r0, #0x0
      bne NoEffect

GetTargetItemEffect:
      ldr r1, .BattleData
      ldr r0, .TargetBank
      ldrb r2, [r0, #0x0]
      mov r0, #0x58
      mul r0, r2
      add r6, r0, r1 /*save Target Data in r6 for quick access*/
      ldrh r0, [r6, #0x2E]
      mov r7, r0    /*save Item Buffer in r7 for quick access*/
      bl EffectGetter

CheckTable:
      ldr r3, .TableLoc
Loop:
      ldrb r2, [r3, #0x0]
      cmp r2, #0xFF
      beq NoEffect
      cmp r2, r0
      beq EntryFound
      add r3, #0x8
      b Loop

EntryFound:
      ldr r0, [r3, #0x4]
      bx r0

NoEffect:
      ldr r0, .Return
      bx r0

EffectGetter:
      ldr r2, =0x809A924+1
      bx r2

.align 2
.Outcome: .word 0x02023DCC
.BattleData: .word 0x02023BE4
.TargetBank: .word 0x02023D6C
.TableLoc: .word 0x08730060
.Return: .word 0x080237C8+1


Table at x730060 should contain 8 byte entries in the format: [Held Item Effect (byte)] 0 0 0 [HeldItem ASM Pointer + 1 in litte endian format](4 bytes) and must be terminated by a FF

Table at xTTTTTT:
Code:

C4 33 02 08 A0 34 02 08 5C 35 02 08 80 35 02 08 98 35 02 08 C0 35 02 08 E4 35 02 08 8C 36 02 08 02 37 02 08 38 37 02 08 D8 37 02 08 XX+1 XX XX 08 CC 36 02 08 EC 36 02 08 1C 38 02 08 60 38 02 08 40 3A 02 08 28 3B 02 08 B4 3B 02 08


where 0xXXXXXX is the pointer to the loader routine.

At x23378: insert pointer to 0x8TTTTTT
At x23366, x23BC0, x23bd6, x23be0 & x23bec: insert 0x12 (i.e. New No. Of End Move Table Entries)
At x1d6ABC, x1d6ad7, x1d6d48, x1d7661, x1d7b76, x1d7b8e, x1d7cd8, x1d839a, x1d94e6, x1d9500 & x1d9517: insert 49 02 11 (No. Of Entries - 1).
In custom battle scripts for Rototiller, Flower Shield etc. and the updated Multi-target moves like Surf, Discharge etc. replace each occurence of cmd49 0x2 0x10 with cmd49 0x2 0x11.



Rocky Helmet:-
Spoiler:

Routine:
Spoiler:
Code:

.text
.align 2
.thumb
.thumb_func
.global rockyhelmet

CheckMagicGuard:
      ldr r1, .BattleStruct
      ldr r0, .UserBank
      ldrb r2, [r0, #0x0]
      mov r0, #0x58
      mul r0, r2
      add r3, r0, r1
      ldrb r0, [r3]
      cmp r0, #0x73 /*Magic Guard*/
      beq NoRocky

HPCheck:
      ldrh r0, [r3, #0x8]
      cmp r0, #0x0
      beq NoRocky

CheckDamage:
      ldr r2, .DamageStruct
      ldr r0, .UserBank
      add r0, #0x1
      ldrb r1, [r0, #0x0]
      lsl r0, r1, #0x2
      add r0, r0, r1
      lsl r1, r0, #0x2
      add r0, r2, #0x4
      add r0, r1, r0
      ldr r1, [r0, #0x0]
      cmp r1, #0x0
      beq NoRocky

CheckContactMove:
      ldr r1, .CurrMove
      ldr r2, .MoveData
      ldrh r1, [r1]
      lsl r0, r1, #1
      add r0, r0, r1
      lsl r0, r0, #2
      add r0, r0, r2
      ldrb r0, [r0, #0x8]
      lsl r0, r0, #0x1F
      cmp r0, #0x0
      beq NoRocky

SetRecoilDamageAndScript:
      ldrh r0, [r3, #0xC]
      mov r1, #0x6
      ldr r2, .Divider
      bl SubRoutCall
      cmp r0, #0x0
      bne NoZero
      mov r0, #0x1

NoZero:
      ldr r1, .Damage
      strh r0, [r1]
      ldr r2, .ScriptPusher
      bl SubRoutCall
      ldr r1, .ScriptPointer
      ldr r0, .RockyHelmetBS
      str r0, [r1]
      ldr r1, .StringArguement
      ldr r0, .StringOffset
      str r0, [r1]
      ldr r1, .ItemBuffer
      strh r7, [r1]
      ldr r2, .ReturnPass
      bx r2

SubRoutCall:
      mov pc, r2

NoRocky:
      ldr r2, .ReturnFail
      bx r2

.align 2
.Damage: .word 0x2023D50
.DamageStruct: .word 0x02023ECC
.CurrMove: .word 0x02023D4A
.BattleStruct: .word 0x02023C04
.UserBank: .word 0x02023D6B
.ScriptPointer: .word 0x02023D74
.StringArguement: .word 0x0203C020
.ItemBuffer: .word 0x02023D68
.StringOffset: .word 0x8DDDDDD
.RockyHelmetBS: .word 0x08AAAAAA

.ScriptPusher: .word 0x8017544+1
.Divider: .word 0x081E4018+1
.ReturnPass: .word 0x080236FC+1
.ReturnFail: .word 0x080237C8+1
.MoveData: .word 0x08250C04




Battle Script at AAAAAA:
Spoiler:

Code:

35 D0 3D 02 02 00 01 10 00 0B 01 0C 01 10 84 01 12 40 00 19 01 00 00 00 00 00 3C




Battle String at DDDDDD:
Code:

FD 10 B4 E7 00 FD 16 FE DC E9 E6 E8 00 FD 0F AB FF




Weakness Policy:-
Spoiler:


Routine:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global weaknesspolicy

CheckSuperEffectiveness:
      ldr r1, .Outcome
      ldrb r0, [r1]
      mov r2, #0x2
      and r0, r2
      cmp r0, #0x0
      beq NoPolicy

CheckDamage:
      ldr r2, .DamageStruct
      ldr r0, .UserBank
      add r0, #0x1
      ldrb r1, [r0, #0x0]
      lsl r0, r1, #0x2
      add r0, r0, r1
      lsl r1, r0, #0x2
      add r0, r2, #0x4
      add r0, r1, r0
      ldr r1, [r0, #0x0]
      cmp r1, #0x0
      beq NoPolicy

CheckTargetHP:
      ldrh r0, [r6, #0x28]
      cmp r0, #0x0
      beq NoPolicy

CheckTargetSubstitute:
      ldr r0, [r6, #0x50]
      mov r1, #0x1
      lsl r1, r1, #0x18
      and r0, r1
      cmp r0, #0x0
      bne NoPolicy

SetPolicyScript:
      ldr r2, .ScriptPusher
      bl SubRoutCall
      ldr r1, .ScriptPointer
      ldr r0, .WeaknessPolicyBS
      str r0, [r1]
      ldr r1, .ItemBuffer
      strh r7, [r1]
      ldr r2, .ReturnPass

SubRoutCall:
      mov pc, r2

NoPolicy:
      ldr r2, .ReturnFail
      bx r2

.align 2
.Outcome: .word 0x02023DCC
.DamageStruct: .word 0x02023ECC
.BattleStruct: .word 0x02023BE4
.UserBank: .word 0x02023D6B
.ScriptPointer: .word 0x02023D74
.ItemBuffer: .word 0x02023D68
.WeaknessPolicyBS: .word 0x08AAAAAA
.ScriptPusher: .word 0x8017544+1
.ReturnPass: .word 0x080236FC+1
.ReturnFail: .word 0x080237C8+1




Battle Script at AAAAAA:
Spoiler:

Code:

#dynamic 0x730400
#freespacebyte 0xFF

#org @start
jumpifstat 0x0 0x3 0x1 0xC @attack2
jumpifstat 0x0 0x0 0x4 0xC @ret

#org @attack2
removeitem 0x0
setbyte 0x2023FDF 0x0
playstatchangeanimation 0x0 0x12 0x0
setbyte 0x2023FDE 0x21
statbuffchange 0x0 false @spatk2
jumpifbyte 0x0 0x2023E87 0x2 @spatk2
setword 0x2023C020 0x8DDDDDD
printstring 0x184
waitmessage 0x40

#org @spatk2
setbyte 0x2023FDE 0x24
statbuffchange 0x0 false @ret
jumpifbyte 0x0 0x2023E87 0x2 @ret
setword 0x2023C020 0x8DDDDDD
printstring 0x184
waitmessage 0x40

#org @ret
return




Battle String at DDDDDD:
Code:

FD 10 B4 E7 00 FD 16 00 E7 DC D5 E6 E4 E0 ED FE E6 D5 DD E7 D9 D8 00 DD E8 E7 00 FD 00 AB FF




Knock Off Ban-list Hook:-
Spoiler:


Good place to put logic to prevent removal of specific Mega Stone on a Mega-evolving mon, or Plates on a Multitype mon.
Also prevents loss of Weakness Policy due to a Super-Effective Knock Off.

Code:

.text
.align 2
.thumb
.thumb_func
.global knockoffbanlist

CheckStickyHold:
      add r0, #0x20
      ldrb r2, [r0]
      cmp r2, #0x3C
      beq Sticky

CheckItem:
      ldrh r0, [r1, #0x2E]
      cmp r0, #0x0
      beq NoItem

BanList:
      push {r3-r4,r7}
      mov r3, r0

CheckOutcome:
      ldr r1, .Outcome
      ldrb r0, [r1]
      mov r2, #0x2
      and r0, r2
      cmp r0, #0x0
      beq CheckOthers

CheckWeaknessPolicy:
      mov r0, r3
      bl GetEffect
      cmp r0, #0xKK
      beq PopBeforeFail

CheckOthers:
    /* Write you code here for Non-Removable Mega Stones,  etc.*/
RemovableItem:
      pop {r3-r4,r7}
      ldr r0, =0x0802105E+1
      bx r0

PopBeforeFail:
      pop {r3-r4,r7}

NoItem:
      ldr r0, =0x080210EC+1
      bx r0

Sticky:
      ldr r0, =0x08021030+1
      bx r0

GetEffect:
      ldr r1, =0x0809A924+1
      bx r1

.align 2
.Outcome: .word 0x02023DCC
/*KK is the effect byte of Weakness Policy*/
/*At x21028: 00 4A 10 47 XX+1 XX XX 08*/



jiangzhengwenjzw November 4th, 2015 7:02 AM

Quote:

Originally Posted by Lance32497 (Post 8982302)
I dunno why it happens, how will I show the other choices?
this is the script that I made
Spoiler:

#org 0x8ECED1
lock
setvar 0x8000 0xA
setvar 0x8001 0xA
setvar 0x8002 0x20
setvar 0x8003 0x1
setvar 0x8004 0x0
setvar 0x8005 0x0
setvar 0x8006 0x0
setvar 0x8007 0x8
setvar 0x8008 0xF
setvar 0x8009 0xF
callasm 0x9800001
waitstate
release
end

I've seen your post, but I'm not sure about what occurred. Currently I'm very busy so I can't test it, but when I have time, I will try to redo the function. I can only suggest you to reduce the value of var_8000 to some value like 7 or 4 now, as the original game uses them.

Desinishon November 5th, 2015 12:32 AM

Hey everybody , I just want to ask is there any way to restrict main player from adding a certain pokemon in PC storage system ( ROM base : Pokemon Emerald)

EdgeZard X November 6th, 2015 8:55 AM

Hi,

I have some requests for Fire Red 1.0 (if they're possible using ASM)

- increasing the EV limit for vitamins from 100 to 252 (since 255 is redundant)
- changing the number of Pokémon affected by Soul Dew (in this case, to four Pokémon (the two extra Pokémon have indexes 0x20b and 0x20c))
- changing Exp Share to give 50% Exp to the holding Pokémon regardless of how much Pokémon are holding it (I'm not sure if this has already been done or not)

Lance32497 November 6th, 2015 4:34 PM

Quote:

Originally Posted by desinishon (Post 8986220)
Hey everybody , I just want to ask is there any way to restrict main player from adding a certain pokemon in PC storage system ( ROM base : Pokemon Emerald)

It can be done via script

Blah November 6th, 2015 4:43 PM

Quote:

Originally Posted by Lance32497 (Post 8987828)
It can be done via script

I don't think you can do it with a script :/
Maybe you can share how?

Lance32497 November 6th, 2015 5:16 PM

Quote:

Originally Posted by FBI (Post 8987840)
I don't think you can do it with a script :/
Maybe you can share how?

there's a code in Eme that can checkthe index number of a Pokémon right, by just editng the PC script before the player presses deposit, then it will do the trick, butvif he wants a set-up where the player enters to deposit Pokemon PC and then when he puts his pokemon on a certain box, a script will pop-up saying "it cannot be placed here" or something, then it really needs an asm routine XD

Desinishon November 9th, 2015 12:07 AM

Quote:

Originally Posted by Lance32497 (Post 8987887)
there's a code in Eme that can checkthe index number of a Pokémon right, by just editng the PC script before the player presses deposit, then it will do the trick, butvif he wants a set-up where the player enters to deposit Pokemon PC and then when he puts his pokemon on a certain box, a script will pop-up saying "it cannot be placed here" or something, then it really needs an asm routine XD

No I don't want " it cannot be placed here" like something I just want to restrict him from adding a pokemon like first u say with a certain code, can you elaborate it to me how to do . I just started hacking emerald recently .

(P.S: plz sorry for my late reply and thanks for helping me out)

kleenexfeu November 11th, 2015 2:43 PM

Quote:

Originally Posted by KDS (Post 8985476)
Battle End Move Target Held Items (FR):-

Loader Routine:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global targetitemloader

CheckOutcome:
      ldr r1, .Outcome
      ldrb r0, [r1]
      mov r1, #0x29
      and r0, r1
      cmp r0, #0x0
      bne NoEffect

GetTargetItemEffect:
      ldr r1, .BattleData
      ldr r0, .TargetBank
      ldrb r2, [r0, #0x0]
      mov r0, #0x58
      mul r0, r2
      add r6, r0, r1 /*save Target Data in r6 for quick access*/
      ldrh r0, [r6, #0x2E]
      mov r7, r0    /*save Item Buffer in r7 for quick access*/
      bl EffectGetter

CheckTable:
      ldr r3, .TableLoc
Loop:
      ldrb r2, [r3, #0x0]
      cmp r2, #0xFF
      beq NoEffect
      cmp r2, r0
      beq EntryFound
      add r3, #0x8
      b Loop

EntryFound:
      ldr r0, [r3, #0x4]
      bx r0

NoEffect:
      ldr r0, .Return
      bx r0

EffectGetter:
      ldr r2, =0x809A924+1
      bx r2

.align 2
.Outcome: .word 0x02023DCC
.BattleData: .word 0x02023BE4
.TargetBank: .word 0x02023D6C
.TableLoc: .word 0x08730060
.Return: .word 0x080237C8+1


Table at x730060 should contain 8 byte entries in the format: [Held Item Effect (byte)] 0 0 0 [HeldItem ASM Pointer + 1 in litte endian format](4 bytes) and must be terminated by a FF

Table at xTTTTTT:
Code:

C4 33 02 08 A0 34 02 08 5C 35 02 08 80 35 02 08 98 35 02 08 C0 35 02 08 E4 35 02 08 8C 36 02 08 02 37 02 08 38 37 02 08 D8 37 02 08 XX+1 XX XX 08 CC 36 02 08 EC 36 02 08 1C 38 02 08 60 38 02 08 40 3A 02 08 28 3B 02 08 B4 3B 02 08


where 0xXXXXXX is the pointer to the loader routine.

At x23378: insert pointer to 0x8TTTTTT
At x23366, x23BC0, x23bd6, x23be0 & x23bec: insert 0x12 (i.e. New No. Of End Move Table Entries)
At x1d6ABC, x1d6ad7, x1d6d48, x1d7661, x1d7b76, x1d7b8e, x1d7cd8, x1d839a, x1d94e6, x1d9500 & x1d9517: insert 49 02 11 (No. Of Entries - 1).
In custom battle scripts for Rototiller, Flower Shield etc. and the updated Multi-target moves like Surf, Discharge etc. replace each occurence of cmd49 0x2 0x10 with cmd49 0x2 0x11.



Rocky Helmet:-
Spoiler:

Routine:
Spoiler:
Code:

.text
.align 2
.thumb
.thumb_func
.global rockyhelmet

CheckMagicGuard:
      ldr r1, .BattleStruct
      ldr r0, .UserBank
      ldrb r2, [r0, #0x0]
      mov r0, #0x58
      mul r0, r2
      add r3, r0, r1
      ldrb r0, [r3]
      cmp r0, #0x73 /*Magic Guard*/
      beq NoRocky

HPCheck:
      ldrh r0, [r3, #0x8]
      cmp r0, #0x0
      beq NoRocky

CheckDamage:
      ldr r2, .DamageStruct
      ldr r0, .UserBank
      add r0, #0x1
      ldrb r1, [r0, #0x0]
      lsl r0, r1, #0x2
      add r0, r0, r1
      lsl r1, r0, #0x2
      add r0, r2, #0x4
      add r0, r1, r0
      ldr r1, [r0, #0x0]
      cmp r1, #0x0
      beq NoRocky

CheckContactMove:
      ldr r1, .CurrMove
      ldr r2, .MoveData
      ldrh r1, [r1]
      lsl r0, r1, #1
      add r0, r0, r1
      lsl r0, r0, #2
      add r0, r0, r2
      ldrb r0, [r0, #0x8]
      lsl r0, r0, #0x1F
      cmp r0, #0x0
      beq NoRocky

SetRecoilDamageAndScript:
      ldrh r0, [r3, #0xC]
      mov r1, #0x6
      ldr r2, .Divider
      bl SubRoutCall
      cmp r0, #0x0
      bne NoZero
      mov r0, #0x1

NoZero:
      ldr r1, .Damage
      strh r0, [r1]
      ldr r2, .ScriptPusher
      bl SubRoutCall
      ldr r1, .ScriptPointer
      ldr r0, .RockyHelmetBS
      str r0, [r1]
      ldr r1, .StringArguement
      ldr r0, .StringOffset
      str r0, [r1]
      ldr r1, .ItemBuffer
      strh r7, [r1]
      ldr r2, .ReturnPass
      bx r2

SubRoutCall:
      mov pc, r2

NoRocky:
      ldr r2, .ReturnFail
      bx r2

.align 2
.Damage: .word 0x2023D50
.DamageStruct: .word 0x02023ECC
.CurrMove: .word 0x02023D4A
.BattleStruct: .word 0x02023C04
.UserBank: .word 0x02023D6B
.ScriptPointer: .word 0x02023D74
.StringArguement: .word 0x0203C020
.ItemBuffer: .word 0x02023D68
.StringOffset: .word 0x8DDDDDD
.RockyHelmetBS: .word 0x08AAAAAA

.ScriptPusher: .word 0x8017544+1
.Divider: .word 0x081E4018+1
.ReturnPass: .word 0x080236FC+1
.ReturnFail: .word 0x080237C8+1
.MoveData: .word 0x08250C04




Battle Script at AAAAAA:
Spoiler:

Code:

35 D0 3D 02 02 00 01 10 00 0B 01 0C 01 10 84 01 12 40 00 19 01 00 00 00 00 00 3C




Battle String at DDDDDD:
Code:

FD 10 B4 E7 00 FD 16 FE DC E9 E6 E8 00 FD 0F AB FF




Weakness Policy:-
Spoiler:


Routine:
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global weaknesspolicy

CheckSuperEffectiveness:
      ldr r1, .Outcome
      ldrb r0, [r1]
      mov r2, #0x2
      and r0, r2
      cmp r0, #0x0
      beq NoPolicy

CheckDamage:
      ldr r2, .DamageStruct
      ldr r0, .UserBank
      add r0, #0x1
      ldrb r1, [r0, #0x0]
      lsl r0, r1, #0x2
      add r0, r0, r1
      lsl r1, r0, #0x2
      add r0, r2, #0x4
      add r0, r1, r0
      ldr r1, [r0, #0x0]
      cmp r1, #0x0
      beq NoPolicy

CheckTargetHP:
      ldrh r0, [r6, #0x28]
      cmp r0, #0x0
      beq NoPolicy

CheckTargetSubstitute:
      ldr r0, [r6, #0x50]
      mov r1, #0x1
      lsl r1, r1, #0x18
      and r0, r1
      cmp r0, #0x0
      bne NoPolicy

SetPolicyScript:
      ldr r2, .ScriptPusher
      bl SubRoutCall
      ldr r1, .ScriptPointer
      ldr r0, .WeaknessPolicyBS
      str r0, [r1]
      ldr r1, .ItemBuffer
      strh r7, [r1]
      ldr r2, .ReturnPass

SubRoutCall:
      mov pc, r2

NoPolicy:
      ldr r2, .ReturnFail
      bx r2

.align 2
.Outcome: .word 0x02023DCC
.DamageStruct: .word 0x02023ECC
.BattleStruct: .word 0x02023BE4
.UserBank: .word 0x02023D6B
.ScriptPointer: .word 0x02023D74
.ItemBuffer: .word 0x02023D68
.WeaknessPolicyBS: .word 0x08AAAAAA
.ScriptPusher: .word 0x8017544+1
.ReturnPass: .word 0x080236FC+1
.ReturnFail: .word 0x080237C8+1




Battle Script at AAAAAA:
Spoiler:

Code:

#dynamic 0x730400
#freespacebyte 0xFF

#org @start
jumpifstat 0x0 0x3 0x1 0xC @attack2
jumpifstat 0x0 0x0 0x4 0xC @ret

#org @attack2
removeitem 0x0
setbyte 0x2023FDF 0x0
playstatchangeanimation 0x0 0x12 0x0
setbyte 0x2023FDE 0x21
statbuffchange 0x0 false @spatk2
jumpifbyte 0x0 0x2023E87 0x2 @spatk2
setword 0x2023C020 0x8DDDDDD
printstring 0x184
waitmessage 0x40

#org @spatk2
setbyte 0x2023FDE 0x24
statbuffchange 0x0 false @ret
jumpifbyte 0x0 0x2023E87 0x2 @ret
setword 0x2023C020 0x8DDDDDD
printstring 0x184
waitmessage 0x40

#org @ret
return




Battle String at DDDDDD:
Code:

FD 10 B4 E7 00 FD 16 00 E7 DC D5 E6 E4 E0 ED FE E6 D5 DD E7 D9 D8 00 DD E8 E7 00 FD 00 AB FF




Knock Off Ban-list Hook:-
Spoiler:


Good place to put logic to prevent removal of specific Mega Stone on a Mega-evolving mon, or Plates on a Multitype mon.
Also prevents loss of Weakness Policy due to a Super-Effective Knock Off.

Code:

.text
.align 2
.thumb
.thumb_func
.global knockoffbanlist

CheckStickyHold:
      add r0, #0x20
      ldrb r2, [r0]
      cmp r2, #0x3C
      beq Sticky

CheckItem:
      ldrh r0, [r1, #0x2E]
      cmp r0, #0x0
      beq NoItem

BanList:
      push {r3-r4,r7}
      mov r3, r0

CheckOutcome:
      ldr r1, .Outcome
      ldrb r0, [r1]
      mov r2, #0x2
      and r0, r2
      cmp r0, #0x0
      beq CheckOthers

CheckWeaknessPolicy:
      mov r0, r3
      bl GetEffect
      cmp r0, #0xKK
      beq PopBeforeFail

CheckOthers:
    /* Write you code here for Non-Removable Mega Stones,  etc.*/
RemovableItem:
      pop {r3-r4,r7}
      ldr r0, =0x0802105E+1
      bx r0

PopBeforeFail:
      pop {r3-r4,r7}

NoItem:
      ldr r0, =0x080210EC+1
      bx r0

Sticky:
      ldr r0, =0x08021030+1
      bx r0

GetEffect:
      ldr r1, =0x0809A924+1
      bx r1

.align 2
.Outcome: .word 0x02023DCC
/*KK is the effect byte of Weakness Policy*/
/*At x21028: 00 4A 10 47 XX+1 XX XX 08*/



Awesome !

I have a question though, are you sure that hook would be enough for Arceus plates and the mega stones ? Because I saw three more check for sticky hold for the moves like thief, trick and I don't remember the last.

Trainer 781 November 11th, 2015 4:18 PM

Quote:

Originally Posted by kleenexfeu (Post 8993373)
Awesome !

I have a question though, are you sure that hook would be enough for Arceus plates and the mega stones ? Because I saw three more check for sticky hold for the moves like thief, trick and I don't remember the last.

Yes, this will be not sufficient. There are total of 3 checks IIRC: knock off, thief and trick.
A good trick would be to create a custom bl to determine removability of an item then refer
the bl from these three locations + knock off multiplier in the damagecalc function.

Lance32497 November 13th, 2015 7:43 PM

Quote:

Originally Posted by FBI (Post 8876273)

OAM routines


Could it be possible to load other tables of OAMs? Like the Pokémon Icon, arrows or a table of sprites? It would be cool if it does that, and 256x512 Sprite, I hope, should be also implemented on this routine.

azurile13 November 14th, 2015 12:54 PM

Quote:

Originally Posted by pokemontutorialTV (Post 8996740)
Code:

.text
.align 2
.thumb
.thumb_func

main:
    push {r0-r4, lr}
    ldr r1, =(0x20370C0) @var 0x8004
    ldrb r1, [r1]
    mov r2, #0x64
    mul r1, r1, r2
    ldr r0, =(0x2024284)
    add r0, r0, r1 @slot
    mov r4, r0 @save slot
    mov r1, #0x2E
    ldr r3, =(0x803FBE8 +1)
    bl linker
    cmp r0, #0x1
    beq setZero
    mov r0, #0x1
    b setNew

setZero:
    mov r0, #0x0

setNew:
    lsl r0, r0, #0x18
    lsr r0, r0, #0x18
    ldr r2, =(0x20370D0) @set inverse
    strb r0, [r2]
    mov r0, r4
    mov r1, #0x2E
    ldr r3, =(0x804037C +1)
    bl linker
    pop {r0-r4, pc}

linker:
    bx r3

.align 2


This should prevent the ability be changed, if the Pokémon doesnt have a secound one, but sadly it gets swapped too ("--------- Pokémon has no ability.")
Anyone have a idea how to fix this?

After the conditional branch to set the ability bit to zero, instead of automatically setting to one, use getattr again to check for species with r1 set to 0xB. Then check to make sure a (non-zero) ability exists in the second slot of the species. Alternatively, you could literally change the second ability of every mon with only one ability to match the first slot. But that won't directly produce an "error" return which would probably be useful for an ability capsule or something similar.

Trainer 781 November 15th, 2015 7:57 AM

First Side Routine Rewrite
A rewrite of the pokemon turn order comparison routine during battles. It does not add any new features but decomposes the routine into a routine with 3 sub-modules which makes it easier to add new speed altering abilities and items (hooking in the original one required to make dual checks).

The rewrite also avoids redundant calculations. For example, if move priorities do not match then no need to calculate and compare effective speeds of the banked mons.
One of the sub-module returns the effective speed of the banked mon so it can readily used for accurate base power calculation of Gyro Ball and Electro Ball.


Spoiler:

.text
.align 2
.thumb
.thumb_func
.global bc_firstside_rewrite_hack
.org 0x14cD8

@MIf the modifed routine crosses x150A8 a hook will be required.
@Current Length: x220 bytes. Ends at x14f08

Main:
push {r4-r7,lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
add sp, #-0x4
lsl r0, r0, #0x18
lsr r0, r0, #0x18 @Bank1
mov r9, r0
lsl r1, r1, #0x18
lsr r1, r1, #0x18
mov r10, r1 @Bank2
mov r0, #0x0
str r0, [sp, #0x0]

TurnModeCheck:
cmp r2, #0x0
bne SpeedCheck

CheckPriority:
mov r0, r9
bl LoadSelectionPriority
lsl r0, r0, #0x18
asr r3, r0, #0x18
mov r8, r3
mov r0, r10
bl LoadSelectionPriority
lsl r0, r0, #0x18
asr r4, r0, #0x18
mov r3, r8
cmp r3, r4
beq SpeedCheck
cmp r3, r4
bge Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]
b Exit

SpeedCheck:
mov r0, r9
bl BracketAlteration
mov r8, r0
mov r0, r10
bl BracketAlteration
mov r4, r0
mov r3, r8
cmp r3, r4
beq LoadBankSpeeds
cmp r3, r4
bge Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]
b Exit

LoadBankSpeeds:
mov r0, r9
bl GetSpeed
mov r8, r0
mov r0, r10
bl GetSpeed
mov r4, r0
mov r3, r8
cmp r3, r4
bne NoTie
bl 0x44EC8
mov r1, #0x1
and r0, r1
cmp r0, #0x0
bne Exit
mov r2, #0x2 @Speed Tied
str r2, [sp, #0x0]
b Exit

NoTie:
cmp r3, r4 @This can be Reversed for Trick Room
bcs Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]

Exit:
ldr r0, [sp, #0x0]
add sp, #0x4
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r1}
bx r1

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
LoadSelectionPriority:
mov r3, r0

LoadMenuChoice:
ldr r0, .MenuChoice
add r1, r3, r0
mov r0, #0x0
ldrb r1, [r1]
cmp r1, #0x0
bne Exit2

FightOptionChosen:
ldr r0, .ProtectStruct
lsl r1, r3, #0x4
add r1, r1, r0
ldrb r0, [r1]
lsl r0, r0, #0x1D
cmp r0, #0x0
bge LoadMoveIndex

Struggle:
mov r4, #0xA5
b LoadPriority

LoadMoveIndex:
ldr r0, .DP08_Pointer
ldr r0, [r0, #0x0]
add r0, r3
add r0, #0x80
ldrb r0, [r0] @Moveset Slot No. Chosen
lsl r0, r0, #0x1
mov r1, #0x58
mul r1, r3
add r0, r0, r1
ldr r1, .BattleStruct
add r0, r0, r1
ldrh r4, [r0, #0xC]

LoadPriority:
ldr r2, .MoveData
lsl r0, r4, #0x1
add r0, r0, r4
lsl r0, r0, #0x2
add r0, r0, r2
ldrb r0, [r0, #0x7]
@Gale Wings And Prankster can be added here easily

Exit2:
bx lr

.align 2
.MenuChoice: .word 0x02023D7C
.ProtectStruct: .word 0x02023E8C
.DP08_Pointer: .word 0x02023FE8
.BattleStruct: .word 0x02023Be4
.MoveData: .word 0x08250c04


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
BracketAlteration: @Return 1 if Quick Claw activates, otherwise 0. Can be called in the

use of Quick Claw Message Battle Script
push {lr}
mov r7, #0x0
mov r3, r0
mov r1, #0x58
ldr r0, .BattleStruct2
mul r1, r3
add r4, r0, r1

CheckItem:
ldrh r0, [r4, #0x2e]
cmp r0, #0xAF
bne LoadItemEffect

EnigmaBerry:
ldr r1, .EnigmaRamArea
lsl r0, r3, #0x3
sub r0, r0, r3
lsl r0, r0, #0x2
add r0, r0, r1
ldrb r6, [r0, #0x7]
ldrb r5, [r0, #0x1A]
b QuickClawCheck

LoadItemEffect:
bl 0x09A924
lsl r0, r0, #0x18
lsr r6, r0, #0x18
ldrh r0, [r4, #0x2e]
bl 0x09A948
lsl r0, r0, #0x18
lsr r5, r0, #0x18

QuickClawCheck: @Can be expanded to include Custap Berry, Lagging Tail, Stall
cmp r6, #0x1A
bne Exit3

LoadActivationChance:
ldr r0, .RandomNoLoc
ldrh r4, [r0]
lsl r0, r5, #0x10
sub r0, r0, r5
mov r1, #0x64
bl 0x1E4018
cmp r4, r0
bge Exit3
mov r7, #0x1

Exit3:
mov r0, r7

PopRegister:
pop {r1}
bx r1

.align 2
.BattleStruct2: .word 0x2023Be4
.RandomNoLoc: .word 0x2023E80
.EnigmaRamArea: .word 0x2023F54

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
@The speed BL that can be used for Gyro Ball and Electro Ball.
@All speed abilities will go here

GetSpeed:

push {lr}
add sp, #-0x4
mov r7, r0
mov r5, #0x58
ldr r6, .BattleStruct3
mul r5, r7
add r6, r5, r6
mov r5, #0x1
str r0, [sp, #0x0]

CloudNineCheck:
mov r0, #0x13
mov r1, #0x0
mov r2, #0xD
mov r3, #0x0
bl 0x019F18
lsl r0, r0, #0x18
cmp r0, #0x0
bne CheckStat

AirLockCheck:
mov r0, #0x0
str r0, [sp, #0x0]
mov r0, #0x13
mov r1, #0x0
mov r2, #0x4D
mov r3, #0x0
bl 0x019F18
lsl r0, r0, #0x18
cmp r0, #0x0
bne CheckStat

LoadWeather:
ldr r4, .WeatherFlags
ldrh r4, [r4]
add r2, r2, r6
add r2, #0x20
ldrb r2, [r2]

CheckRain:
mov r0, #0x7
and r0, r4
cmp r0, #0x0
beq CheckSunlight
cmp r2, #0x21
beq WeatherBoost

CheckSunlight:
mov r0, #0x60
and r0, r4
cmp r0, #0x0
beq CheckStat
cmp r2, #0x22
bne CheckStat

WeatherBoost:
mov r5, #0x2

CheckStat:
MultiplySpeedAccToStat:
ldrh r3, [r6, #0x6]
mul r5, r3 @Speed
ldr r2, .StatFactors
ldrb r1, [r6, #0x1B]
lsl r1, r1, #0x1
add r2, r1, r2
ldrb r0, [r2]
mul r0, r5
ldrb r1, [r2, #0x1]
bl 0x1E4018
mov r4, r0 @Speed

CheckItem2:
ldrh r0, [r6, #0x2e]
cmp r0, #0xAF
bne LoadItemEffect2

EnigmaBerry2:
ldr r1, .EnigmaRamArea2
lsl r0, r7, #0x3
sub r0, r0, r3
lsl r0, r0, #0x2
add r0, r0, r1
ldrb r0, [r0, #0x7]
b MachoCheck

LoadItemEffect2:
bl 0x09a924
lsl r0, r0, #0x18
lsr r0, r0, #0x18

MachoCheck:
cmp r0, #0x18
bne ParalysisCheck
lsr r4, r4, #0x1

ParalysisCheck:
ldr r0, [r6, #0x4C]
mov r1, #0x40
and r0, r1
cmp r0, #0x0
beq Exit4
lsr r4, r4, #0x2

Exit4:
mov r0, r4
add sp, #0x4
pop {r1}
bx r1

.align 2
.BattleStruct3: .word 0x2023Be4
.WeatherFlags: .word 0x2023F1c
.StatFactors: .word 0x825DEAD
.EnigmaRamArea2: .word 0x2023F54

MrDollSteak November 15th, 2015 3:32 PM

Quote:

Originally Posted by KDS (Post 8997795)
First Side Routine Rewrite
A rewrite of the pokemon turn order comparison routine during battles. It does not add any new features but decomposes the routine into a routine with 3 sub-modules which makes it easier to add new speed altering abilities and items (hooking in the original one required to make dual checks).

The rewrite also avoids redundant calculations. For example, if move priorities do not match then no need to calculate and compare effective speeds of the banked mons.
One of the sub-module returns the effective speed of the banked mon so it can readily used for accurate base power calculation of Gyro Ball and Electro Ball.

That's really awesome KDS! I had done something similar, but had already added all the new abilities and moves that may come into play. I like how you kept this as an option for Vanilla! Plus yours is far more well explained.

Xencleamas November 16th, 2015 5:28 AM

Callasm and Setword Commands, and Battle String Loader Hack for Emerald

First, you need to expand the Battle Script Commands table that is found on 0x0831BD10. There are 0xF8 (248) commands used and the table is 0x3E4 bytes long. However, every command is only one byte, so there can only be maximum of 256 commands and there will be available of 7 more commands (8 for FireRed because the addition of 0xF8 command in Emerald is used). Here's how you should expand the table:

Spoiler:
  • Go to any free space of 0x400 bytes. Select 0x400 bytes and fill it with FE FE FE 08.
  • Go to 0x0831BD10. Select and copy 0x3E4 bytes.
  • Go to the offset of your new Battle Script commands table and paste the data there.
  • Replace all 10 BD 31 08 with the "reversed hex in little indian of your new names data offset with 08 at the end"
  • If you want to clear the old data, go back to 0x0831BD10, select 0x3E4 bytes and fill it with FF.
  • You got your new table, right? the preceeding FE FE FE 08-s is where you'll put pointers of your command routines. So, your next commands are 0xF9, 0xFA until 0xFF.


In case you care about existing custom commands in the forums, here is the list (I will dig some other custom commands from Resources Threads):

Callasm:
Spoiler:

Routine
Code:

.text
.align 2
.thumb
.thumb_func
.global battlescriptcallasm
main:
push {lr}
push {r1-r7}
ldr r0, scriptlocation
ldr r0, [r0, #0x0]
ldrb r1, [r0, #0x1]
ldrb r2, [r0, #0x2]
lsl r2, r2, #0x8
orr r1, r2
ldrb r2, [r0, #0x3]
lsl r2, r2, #0x10
orr r1, r2
ldrb r2, [r0, #0x4]
lsl r2, r2, #0x18
orr r1, r2
bl bx_r1
ldr r0, scriptlocation
ldr r1, [r0, #0x0]
add r1, #0x5
str r1, [r0, #0x0]
pop {r1-r7}
pop {r0}
bx r0
bx_r1: bx r1
.align
scriptlocation: .word 0x02024214


Here's the compiled version of the routine:
Code:

00 B5 FE B4 0A 48 00 68 41 78 82 78 12 02 11 43
C2 78 12 04 11 43 02 79 12 06 11 43 00 F0 07 F8
03 48 01 68 05 31 01 60 FE BC 01 BC 00 47 08 47
14 42 02 02




Setword:
Spoiler:

Routine (Setword)
Code:

00 B5 FE B4 14 48 00 68 41 78 82 78 12 02 11 43
C2 78 12 04 11 43 02 79 12 06 11 43 08 1C 06 B4
04 21 00 F0 16 F8 06 BC 80 00 88 42 0E D1 0A 48
02 68 53 79 94 79 24 02 23 43 D4 79 24 04 23 43
14 7A 24 06 23 43 0B 60 09 32 02 60 FE BC 01 BC
00 47 02 4A 10 47 C0 46 14 42 02 02 41 75 2E 08


*Sorry if it is just compiled because I don't have the decompiled version of this.

Make a pointer of this routine in the commands table. The routine above is the command. Then, the next one is the Battle String Loader (it is actually posted here) that will actually work the command.

Routine (Battle String Loader):
Code:

.text
.align 2
.thumb
.thumb_func
.global battlestringloaderhack
main:
mov r0, #0xC2
lsl r0, r0, #0x1
cmp r0, r6
bne normalcode
ldr r0, ramlocation
ldr r7, [r0, #0x0]
cmp r7, #0x0
beq alternative
mov r0, #0xA
lsl r0, r0, #0x18
cmp r7, r0
bge alternative
mov r0, #0x8
lsl r0, r0, #0x18
cmp r7, r0
blt alternative
b continue
alternative: mov r6, #0xC
ldr r1, returntwo
bx r1
continue: ldr r0, returnone
bx r0
normalcode: ldr r1, otherramloc
mov r0, #0xFF
strb r0, [r1, #0x0]
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r0}
bx r0
.align
ramlocation: .word 0x0203E320
returntwo: .word 0x0814E6CD
returnone: .word 0x0814E6D9
otherramloc: .word 0x02022E2C

/* Insert 01 49 08 47 @ 0x0814E6C0 */
/* Insert XX+1 XX XX 08 (the location of the routine) @ 0x0814E6C8 */


Here's the compiled version of the routine:
Code:

C2 20 40 00 B0 42 11 D1 0D 48 07 68 00 2F 08 D0
0A 20 00 06 87 42 04 DA 08 20 00 06 87 42 00 DB
02 E0 0C 26 07 49 08 47 07 48 00 47 07 49 FF 20
08 70 38 BC 98 46 A1 46 AA 46 F0 BC 01 BC 00 47
20 E3 03 02 CD E6 14 08 D9 E6 14 08 2C 2E 02 02

/* Insert 01 49 08 47 @ 0x0814E6C0 */
/* Insert XX+1 XX XX 08 (the location of the routine) @ 0x0814E6C8 */



Inmortal Kaktus November 17th, 2015 12:43 PM

Hi guys, first of all, sorry for my bad English, I don't speak that language. After that...

I come to ask for help with a ASM Routine.

I need load a image in-game, of 16 colors or 256, I don't care. I need load an imagen in a script. Can anybody help me?

kleenexfeu November 17th, 2015 6:09 PM

Quote:

Originally Posted by KDS (Post 8993508)
Yes, this will be not sufficient. There are total of 3 checks IIRC: knock off, thief and trick.
A good trick would be to create a custom bl to determine removability of an item then refer
the bl from these three locations + knock off multiplier in the damagecalc function.

Knock off multiplier should definetly be handled by ASM rather than BS yeah

For the bl, I updated my multitype routines, though it's for emerald. I didn't tested it but it should be ok

pokefreak890 November 18th, 2015 7:30 PM

How exactly do u expand the battle script command table? It doesn't exactly say so I was wondering

mkarthick98 November 19th, 2015 6:46 AM

Could you write an ASM script to name the hero in the overworld? I want to use this, since I intend to skip the intro, while still allowing the user to name themselves.

eMMe97 November 19th, 2015 9:14 AM

Quote:

Originally Posted by mkarthick98 (Post 9002650)
Could you write an ASM script to name the hero in the overworld? I want to use this, since I intend to skip the intro, while still allowing the user to name themselves.

No ASM needed, only a simple script with callasm 0x9FC91 [FireRed(U)]

DraconianWing November 19th, 2015 1:41 PM

I'm not sure if this has been done before in a rom hack, but is there a routine that enables the mother Pokemon to pass down Egg Moves to a child (like in Gen VI breeding)? Or is there just a gender check somewhere in the game that has to be disabled? iirc only the father can pass down Egg Moves in Generation 3.

pokefreak890 November 20th, 2015 4:44 AM

thank you sky high that is so much clearer

HackAbel November 25th, 2015 3:05 PM

Greetings fellow modders! My mod was coming along well until I hit this ASM roadblock. After watching and reading what tutorials I had spare time for, I'm not even sure my idea is possible, so here it goes...

Basically, I want players to be rewarded for sticking with the same party of pokemon throughout.

I'd like to be able to store my "current party pokemon data" in a table/variable during/after a battle (wild, trainer, etc.). It needs to remember the exact pokemon in the party (or at least the species), and store it for an "extended" amount of time. At the end of every battle (wild included) I need to be able to compare the current party pokemon with the data stored in the table, and if the pokemon in my party are the same as the pokemon stored in the table, I need a "counter" to get +1. If they are not the counter has to reset.

Once the counter reaches X amount I can call to another script filled with things I already know are possible.

I would also like to change the way EVs work. Is there a way to remove the EV cap? If so I would prefer there was a way to earn 252 EVs normally (in a single stat), and then every EV after 252 (in that stat), was only 1/100th as effective (IE, you need 400 attack EVs to get +1 attack) I read that division was tricky in an ASM tutorial....

So is something like this possible? Can you think of any substitues if not? As long as the end result is the same idc how I get there.

Thanks for taking the time to read and respond, I hope you're enjoying/enjoyed the holidays!

Pokemon_XY November 26th, 2015 6:28 AM

1 Attachment(s)

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



BLAx501! November 26th, 2015 4:31 PM

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 + update_func)
mov r1, #2
ldr r3, =0x807741D
bl call_r3
ldr r1, =0x20370C0
strh r0, [r1]
pop {r4, pc}
.ltorg

update_func:
push {lr}
bl print_string
pop {pc}

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:

0x6EF1E - 00 00 00 49 08 47 YY+1 YY YY 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



Seems cool, but I suggest you to change something. Why don't you link this functionality to an unused button such as R (remember we can use these two buttons if properly configured)?

Also it would be very interesting to have the option to display this "clock-box" anytime we want via scripting. I'm not sure but by a quick look, it seems to me that the one that displays it is the second one, isn't it??

You should explain, almost briefly, how do this work, anyway, awesome system :D

Pokemon_XY November 26th, 2015 8:35 PM

Quote:

Originally Posted by BLAx501! (Post 9011146)
Seems cool, but I suggest you to change something. Why don't you link this functionality to an unused button such as R (remember we can use these two buttons if properly configured)?

Also it would be very interesting to have the option to display this "clock-box" anytime we want via scripting. I'm not sure but by a quick look, it seems to me that the one that displays it is the second one, isn't it??

You should explain, almost briefly, how do this work, anyway, awesome system :D

If you know some concepts in ASM hacking, I think it won't be hard.
For ques1: In my opinion, triggering automatically is better xD
For ques2: have you heard of JPAN's number input box? It's imitating the 'multichoice' box and you can find how to display a box with a specific string in scripts. Then you can just add a task to the IRAM function queue and updating the time in the box. When you want to hide it, simply delete the task via another 'callasm'.
However, I don't think it necessary to be used in scripts, as I can't imagine a scene using that box xD
For explanation, I just imitate the function to generate the safari box so you can deal with that function to see its inner mechanism.

Lance32497 December 1st, 2015 8:47 PM

So here I am, well I dunno if it's still in development but still I'm hoping that someone would do it.
Here is my request:

Wild Pokemon switch based on Gender
It's like Gen IV and onwards' feature of a certain Pokèmon having a seperated sprite for its opposite gender. Well, if anyone here knows how to check if the player caught a specific Pokèmon not just in party but also "inside the PC" and a way how to let the player check and store seen and/or caught data of Pokèmon in Pokedex then please tell me cuz' I know how to trick this one

kleenexfeu December 6th, 2015 4:35 PM

Quote:

Originally Posted by KDS (Post 8997795)
First Side Routine Rewrite
A rewrite of the pokemon turn order comparison routine during battles. It does not add any new features but decomposes the routine into a routine with 3 sub-modules which makes it easier to add new speed altering abilities and items (hooking in the original one required to make dual checks).

The rewrite also avoids redundant calculations. For example, if move priorities do not match then no need to calculate and compare effective speeds of the banked mons.
One of the sub-module returns the effective speed of the banked mon so it can readily used for accurate base power calculation of Gyro Ball and Electro Ball.


Spoiler:

.text
.align 2
.thumb
.thumb_func
.global bc_firstside_rewrite_hack
.org 0x14cD8

@MIf the modifed routine crosses x150A8 a hook will be required.
@Current Length: x220 bytes. Ends at x14f08

Main:
push {r4-r7,lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
add sp, #-0x4
lsl r0, r0, #0x18
lsr r0, r0, #0x18 @Bank1
mov r9, r0
lsl r1, r1, #0x18
lsr r1, r1, #0x18
mov r10, r1 @Bank2
mov r0, #0x0
str r0, [sp, #0x0]

TurnModeCheck:
cmp r2, #0x0
bne SpeedCheck

CheckPriority:
mov r0, r9
bl LoadSelectionPriority
lsl r0, r0, #0x18
asr r3, r0, #0x18
mov r8, r3
mov r0, r10
bl LoadSelectionPriority
lsl r0, r0, #0x18
asr r4, r0, #0x18
mov r3, r8
cmp r3, r4
beq SpeedCheck
cmp r3, r4
bge Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]
b Exit

SpeedCheck:
mov r0, r9
bl BracketAlteration
mov r8, r0
mov r0, r10
bl BracketAlteration
mov r4, r0
mov r3, r8
cmp r3, r4
beq LoadBankSpeeds
cmp r3, r4
bge Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]
b Exit

LoadBankSpeeds:
mov r0, r9
bl GetSpeed
mov r8, r0
mov r0, r10
bl GetSpeed
mov r4, r0
mov r3, r8
cmp r3, r4
bne NoTie
bl 0x44EC8
mov r1, #0x1
and r0, r1
cmp r0, #0x0
bne Exit
mov r2, #0x2 @Speed Tied
str r2, [sp, #0x0]
b Exit

NoTie:
cmp r3, r4 @This can be Reversed for Trick Room
bcs Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]

Exit:
ldr r0, [sp, #0x0]
add sp, #0x4
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r1}
bx r1

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
LoadSelectionPriority:
mov r3, r0

LoadMenuChoice:
ldr r0, .MenuChoice
add r1, r3, r0
mov r0, #0x0
ldrb r1, [r1]
cmp r1, #0x0
bne Exit2

FightOptionChosen:
ldr r0, .ProtectStruct
lsl r1, r3, #0x4
add r1, r1, r0
ldrb r0, [r1]
lsl r0, r0, #0x1D
cmp r0, #0x0
bge LoadMoveIndex

Struggle:
mov r4, #0xA5
b LoadPriority

LoadMoveIndex:
ldr r0, .DP08_Pointer
ldr r0, [r0, #0x0]
add r0, r3
add r0, #0x80
ldrb r0, [r0] @Moveset Slot No. Chosen
lsl r0, r0, #0x1
mov r1, #0x58
mul r1, r3
add r0, r0, r1
ldr r1, .BattleStruct
add r0, r0, r1
ldrh r4, [r0, #0xC]

LoadPriority:
ldr r2, .MoveData
lsl r0, r4, #0x1
add r0, r0, r4
lsl r0, r0, #0x2
add r0, r0, r2
ldrb r0, [r0, #0x7]
@Gale Wings And Prankster can be added here easily

Exit2:
bx lr

.align 2
.MenuChoice: .word 0x02023D7C
.ProtectStruct: .word 0x02023E8C
.DP08_Pointer: .word 0x02023FE8
.BattleStruct: .word 0x02023Be4
.MoveData: .word 0x08250c04


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
BracketAlteration: @Return 1 if Quick Claw activates, otherwise 0. Can be called in the

use of Quick Claw Message Battle Script
push {lr}
mov r7, #0x0
mov r3, r0
mov r1, #0x58
ldr r0, .BattleStruct2
mul r1, r3
add r4, r0, r1

CheckItem:
ldrh r0, [r4, #0x2e]
cmp r0, #0xAF
bne LoadItemEffect

EnigmaBerry:
ldr r1, .EnigmaRamArea
lsl r0, r3, #0x3
sub r0, r0, r3
lsl r0, r0, #0x2
add r0, r0, r1
ldrb r6, [r0, #0x7]
ldrb r5, [r0, #0x1A]
b QuickClawCheck

LoadItemEffect:
bl 0x09A924
lsl r0, r0, #0x18
lsr r6, r0, #0x18
ldrh r0, [r4, #0x2e]
bl 0x09A948
lsl r0, r0, #0x18
lsr r5, r0, #0x18

QuickClawCheck: @Can be expanded to include Custap Berry, Lagging Tail, Stall
cmp r6, #0x1A
bne Exit3

LoadActivationChance:
ldr r0, .RandomNoLoc
ldrh r4, [r0]
lsl r0, r5, #0x10
sub r0, r0, r5
mov r1, #0x64
bl 0x1E4018
cmp r4, r0
bge Exit3
mov r7, #0x1

Exit3:
mov r0, r7

PopRegister:
pop {r1}
bx r1

.align 2
.BattleStruct2: .word 0x2023Be4
.RandomNoLoc: .word 0x2023E80
.EnigmaRamArea: .word 0x2023F54

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
@The speed BL that can be used for Gyro Ball and Electro Ball.
@All speed abilities will go here

GetSpeed:

push {lr}
add sp, #-0x4
mov r7, r0
mov r5, #0x58
ldr r6, .BattleStruct3
mul r5, r7
add r6, r5, r6
mov r5, #0x1
str r0, [sp, #0x0]

CloudNineCheck:
mov r0, #0x13
mov r1, #0x0
mov r2, #0xD
mov r3, #0x0
bl 0x019F18
lsl r0, r0, #0x18
cmp r0, #0x0
bne CheckStat

AirLockCheck:
mov r0, #0x0
str r0, [sp, #0x0]
mov r0, #0x13
mov r1, #0x0
mov r2, #0x4D
mov r3, #0x0
bl 0x019F18
lsl r0, r0, #0x18
cmp r0, #0x0
bne CheckStat

LoadWeather:
ldr r4, .WeatherFlags
ldrh r4, [r4]
mov r2, r6 r2 wasn't safe after calling ability_something
add r2, #0x20
ldrb r2, [r2]

CheckRain:
mov r0, #0x7
and r0, r4
cmp r0, #0x0
beq CheckSunlight
cmp r2, #0x21
beq WeatherBoost

CheckSunlight:
mov r0, #0x60
and r0, r4
cmp r0, #0x0
beq CheckStat
cmp r2, #0x22
bne CheckStat

WeatherBoost:
mov r5, #0x2

CheckStat:
MultiplySpeedAccToStat:
ldrh r3, [r6, #0x6]
mul r5, r3 @Speed
ldr r2, .StatFactors
ldrb r1, [r6, #0x1B]
lsl r1, r1, #0x1
add r2, r1, r2
ldrb r0, [r2]
mul r0, r5
ldrb r1, [r2, #0x1]
bl 0x1E4018
mov r4, r0 @Speed

CheckItem2:
ldrh r0, [r6, #0x2e]
cmp r0, #0xAF
bne LoadItemEffect2

EnigmaBerry2:
ldr r1, .EnigmaRamArea2
lsl r0, r7, #0x3
sub r0, r0, r3
lsl r0, r0, #0x2
add r0, r0, r1
ldrb r0, [r0, #0x7]
b MachoCheck

LoadItemEffect2:
bl 0x09a924
lsl r0, r0, #0x18
lsr r0, r0, #0x18

MachoCheck:
cmp r0, #0x18
bne ParalysisCheck
lsr r4, r4, #0x1

ParalysisCheck:
ldr r0, [r6, #0x4C]
mov r1, #0x40
and r0, r1
cmp r0, #0x0
beq Exit4
lsr r4, r4, #0x2

Exit4:
mov r0, r4
add sp, #0x4
pop {r1}
bx r1

.align 2
.BattleStruct3: .word 0x2023Be4
.WeatherFlags: .word 0x2023F1c
.StatFactors: .word 0x825DEAD
.EnigmaRamArea2: .word 0x2023F54

The routines between emerald and FR are almost the same for that part of the engine.
The few exceptions are :
-Emerald check the battleflags of the battle frontier, it one of them is activated, you don't get the boost
from the third badges.
-Fews register are shifted, but since the whole routine has been rewritten, it shouldn't matter.

Since KDS completly removed the boost-speed from the badge, FR-EM routine are totally the same.

So, here is the port, thanks KDS :

First Side Routine Rewrite (update : fix a little typo from KDS's routine)
Spoiler:

Code:

.text
.align 2
.thumb
.thumb_func
.global bc_firstside_rewrite_hack
.org 0x3CF10, 0xFF

@MIf the modifed routine crosses x3D2E6 a hook will be required.
@Current Length: x220 bytes.

Main:
push {r4-r7,lr}
mov r7, r10
mov r6, r9
mov r5, r8
push {r5-r7}
add sp, #-0x4
lsl r0, r0, #0x18
lsr r0, r0, #0x18 @Bank1
mov r9, r0
lsl r1, r1, #0x18
lsr r1, r1, #0x18
mov r10, r1 @Bank2
mov r0, #0x0
str r0, [sp, #0x0]

TurnModeCheck:
cmp r2, #0x0
bne SpeedCheck

CheckPriority:
mov r0, r9
bl LoadSelectionPriority
lsl r0, r0, #0x18
asr r3, r0, #0x18
mov r8, r3
mov r0, r10
bl LoadSelectionPriority
lsl r0, r0, #0x18
asr r4, r0, #0x18
mov r3, r8
cmp r3, r4
beq SpeedCheck
cmp r3, r4
bge Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]
b Exit

SpeedCheck:
mov r0, r9
bl BracketAlteration
mov r8, r0
mov r0, r10
bl BracketAlteration
mov r4, r0
mov r3, r8
cmp r3, r4
beq LoadBankSpeeds
cmp r3, r4
bge Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]
b Exit

LoadBankSpeeds:
mov r0, r9
bl GetSpeed
mov r8, r0
mov r0, r10
bl GetSpeed
mov r4, r0
mov r3, r8
cmp r3, r4
bne NoTie
bl 0x6F5CC @ Emerald
mov r1, #0x1
and r0, r1
cmp r0, #0x0
bne Exit
mov r2, #0x2 @Speed Tied
str r2, [sp, #0x0]
b Exit

NoTie:
cmp r3, r4 @This can be Reversed for Trick Room
bcs Exit @First Bank Wins
mov r2, #0x1 @Second Bank Wins
str r2, [sp, #0x0]

Exit:
ldr r0, [sp, #0x0]
add sp, #0x4
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r1}
bx r1

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
LoadSelectionPriority:
mov r3, r0

LoadMenuChoice:
ldr r0, .MenuChoice
add r1, r3, r0
mov r0, #0x0
ldrb r1, [r1]
cmp r1, #0x0
bne Exit2

FightOptionChosen:
ldr r0, .ProtectStruct
lsl r1, r3, #0x4
add r1, r1, r0
ldrb r0, [r1]
lsl r0, r0, #0x1D
cmp r0, #0x0
bge LoadMoveIndex

Struggle:
mov r4, #0xA5
b LoadPriority

LoadMoveIndex:
ldr r0, .DP08_Pointer
ldr r0, [r0, #0x0]
add r0, r3
add r0, #0x80
ldrb r0, [r0] @Moveset Slot No. Chosen
lsl r0, r0, #0x1
mov r1, #0x58
mul r1, r3
add r0, r0, r1
ldr r1, .BattleStruct
add r0, r0, r1
ldrh r4, [r0, #0xC]

LoadPriority:
ldr r2, .MoveData
lsl r0, r4, #0x1
add r0, r0, r4
lsl r0, r0, #0x2
add r0, r0, r2
ldrb r0, [r0, #0x7]
@Gale Wings And Prankster can be added here easily

Exit2:
bx lr

.align 2
.MenuChoice: .word 0x0202421C @ Emerald
.ProtectStruct: .word 0x0202433C @ Emerald
.DP08_Pointer: .word 0x0202449C @ Emerald
.BattleStruct: .word 0x02024084 @ Emerald
.MoveData: .word 0x831C898 @ Emerald

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
BracketAlteration: @Return 1 if Quick Claw activates, otherwise 0. Can be called in the
@use of Quick Claw Message Battle Script

push {lr}
mov r7, #0x0
mov r3, r0
mov r1, #0x58
ldr r0, .BattleStruct2
mul r1, r3
add r4, r0, r1

CheckItem:
ldrh r0, [r4, #0x2e]
cmp r0, #0xAF
bne LoadItemEffect

EnigmaBerry:
ldr r1, .EnigmaRamArea
lsl r0, r3, #0x3
sub r0, r0, r3
lsl r0, r0, #0x2
add r0, r0, r1
ldrb r6, [r0, #0x7]
ldrb r5, [r0, #0x1A]
b QuickClawCheck

LoadItemEffect:
bl 0x0D74DC @ Emerald
lsl r0, r0, #0x18
lsr r6, r0, #0x18
ldrh r0, [r4, #0x2e]
bl 0x0D7500 @ Emerald
lsl r0, r0, #0x18
lsr r5, r0, #0x18

QuickClawCheck: @Can be expanded to include Custap Berry, Lagging Tail, Stall
cmp r6, #0x1A
bne Exit3

LoadActivationChance:
ldr r0, .RandomNoLoc
ldrh r4, [r0]
lsl r0, r5, #0x10
sub r0, r0, r5
mov r1, #0x64
bl 0x2E7540 @ Emerald
cmp r4, r0
bge Exit3
mov r7, #0x1

Exit3:
mov r0, r7

PopRegister:
pop {r1}
bx r1

.align 2
.BattleStruct2: .word 0x2024084 @ Emerald
.RandomNoLoc: .word 0x2024330 @ Emerald
.EnigmaRamArea: .word 0x2024404 @ Emerald

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.align 2
@The speed BL that can be used for Gyro Ball and Electro Ball.
@All speed abilities will go here

GetSpeed:

push {lr}
add sp, #-0x4
mov r7, r0
mov r5, #0x58
ldr r6, .BattleStruct3
mul r5, r7
add r6, r5, r6
mov r5, #0x1
str r0, [sp, #0x0]

CloudNineCheck:
mov r0, #0x13
mov r1, #0x0
mov r2, #0xD
mov r3, #0x0
bl 0x42828 @ Emerald ability_something
lsl r0, r0, #0x18
cmp r0, #0x0
bne CheckStat

AirLockCheck:
mov r0, #0x0
str r0, [sp, #0x0]
mov r0, #0x13
mov r1, #0x0
mov r2, #0x4D
mov r3, #0x0
bl 0x42828 @ Emerald ability_something
lsl r0, r0, #0x18
cmp r0, #0x0
bne CheckStat

LoadWeather:
ldr r4, .WeatherFlags
ldrh r4, [r4]
mov r2, r6 @ r2 wasn't safe after calling ability_something
add r2, #0x20
ldrb r2, [r2]

CheckRain:
mov r0, #0x7
and r0, r4
cmp r0, #0x0
beq CheckSunlight
cmp r2, #0x21
beq WeatherBoost

CheckSunlight:
mov r0, #0x60
and r0, r4
cmp r0, #0x0
beq CheckStat
cmp r2, #0x22
bne CheckStat

WeatherBoost:
mov r5, #0x2

CheckStat:
MultiplySpeedAccToStat:
ldrh r3, [r6, #0x6]
mul r5, r3 @Speed
ldr r2, .StatFactors
ldrb r1, [r6, #0x1B]
lsl r1, r1, #0x1
add r2, r1, r2
ldrb r0, [r2]
mul r0, r5
ldrb r1, [r2, #0x1]
bl 0x2E7540 @ Emerald
mov r4, r0 @Speed

CheckItem2:
ldrh r0, [r6, #0x2e]
cmp r0, #0xAF
bne LoadItemEffect2

EnigmaBerry2:
ldr r1, .EnigmaRamArea2
lsl r0, r7, #0x3
sub r0, r0, r3
lsl r0, r0, #0x2
add r0, r0, r1
ldrb r0, [r0, #0x7]
b MachoCheck

LoadItemEffect2:
bl 0x0D74DC @ Emerald
lsl r0, r0, #0x18
lsr r0, r0, #0x18

MachoCheck:
cmp r0, #0x18
bne ParalysisCheck
lsr r4, r4, #0x1

ParalysisCheck:
ldr r0, [r6, #0x4C]
mov r1, #0x40
and r0, r1
cmp r0, #0x0
beq Exit4
lsr r4, r4, #0x2

Exit4:
mov r0, r4
add sp, #0x4
pop {r1}
bx r1

.align 2
.BattleStruct3: .word 0x2024084 @ Emerald
.WeatherFlags: .word 0x20243CC @ Emerald
.StatFactors: .word 0x8329D2E @ Emerald
.EnigmaRamArea2: .word 0x2024404 @ Emerald



Joexv December 7th, 2015 9:32 PM

Quote:

Originally Posted by FBI (Post 8528761)

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.

Found a bug, when the player is down to 2 Pokemon and one dies in battle, you cannot exit the "choose your next Pokemon" menu. As a sorta fix for anyone who wants it, right after
Code:

loop:
        ldr r0, =(0x2024029)
        ldrb r4, [r0]
        cmp r5, r4
        beq end


add
Code:

        cmp r4, #0x1
        beq end


So it'll look like this:
Code:

loop:
        ldr r0, =(0x2024029)
        ldrb r4, [r0]
        cmp r5, r4
        beq end
        cmp r4, #0x1
        beq end


What this does, is it simply checks to see if you only have 2 pokemon left, when it goes through to delete your Pokemon, if it's true it just leaves the Pokemon fainted in your Party.(This is untested, but there's no reason it shouldn't work)

Lance32497 December 10th, 2015 12:37 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 8964135)
Wild double battles

I had inserted all the routines in my hack and I'm kind of glad that it doesn't crash the game or make any unwanted errors, well my problem is even though I set the percentage value of double wild pokemon appearance to 64, which is 100%, nothing happens. The grass ID is the default, 0xD, and all are fine.

Do you have any idea why setting it to 64 doesn't create a 100% double wild pokemon appearance?

jiangzhengwenjzw December 10th, 2015 1:48 AM

Quote:

Originally Posted by Lance32497 (Post 9028541)
I had inserted all the routines in my hack and I'm kind of glad that it doesn't crash the game or make any unwanted errors, well my problem is even though I set the percentage value of double wild pokemon appearance to 64, which is 100%, nothing happens. The grass ID is the default, 0xD, and all are fine.

Do you have any idea why setting it to 64 doesn't create a 100% double wild pokemon appearance?

You should have at least 2 Pokemon in your team lol
If it still doesn't work, see VM.

Lance32497 December 10th, 2015 2:26 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 9028575)
You should have at least 2 Pokemon in your team lol
If it still doesn't work, see VM.

*facepalm*

EDIT: Minor bug


as you can see in the video, I only have 2 Pokemon in my party but when 1 of my pokemon faints, it asks to use another pokemon

jiangzhengwenjzw December 10th, 2015 8:32 PM

Quote:

Originally Posted by Lance32497 (Post 9028608)
*facepalm*
as you can see in the video, I only have 2 Pokemon in my party but when 1 of my pokemon faints, it asks to use another pokemon

oh-oh... That's really a glitch never occurred in my mind TAT However, I'm quite busy these days for exam so I can only promise that I will see the problem in the winter vacation in February.

Lance32497 December 11th, 2015 4:07 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 9029939)
oh-oh... That's really a glitch never occurred in my mind TAT However, I'm quite busy these days for exam so I can only promise that I will see the problem in the winter vacation in February.

That's okay, those are just minor bugs, speaking of those, I had encountered bugs again.

When you press no, instead of letting your one pokemon as your last, you'll run into the battle,

also, there are instances that your pokemon's name will be changed to an undescribable weird letters,

sometimes, the HP gets translated to number rather than HP bar image itself,

anyway, it's still a good feature and thanks for sharing it, I do really hope that it will be possible to throw a ball in a 2v2 battle

jiangzhengwenjzw December 11th, 2015 4:51 AM

Quote:

Originally Posted by Lance32497 (Post 9030289)
When you press no, instead of letting your one pokemon as your last, you'll run into the battle,

OK, I haven't taken a look at those "switch" points.
Quote:

also, there are instances that your pokemon's name will be changed to an undescribable weird letters,
sometimes, the hb gets translated to number rather than HP bar image itself,
WADAFAK, I've never encountered with those bugs, sorry.
Quote:

anyway, it's still a good feature and thanks for sharing it, I do really hope that it will be possible to throw a ball in a 2v2 battle
That's meant to imitate the Gen V feature, in which you can't throw a ball when there're 2 pokemon on the field. It also prevent many bugs from occurring.

I'm sorry for those terrible bugs. As I've said, the system is not yet complete and I've only fixed some of the existing bugs and I think its main purpose is to provide some information for other hackers. If the rest bugs can't be fixed recently, I will take a look at them in Feb approximately.

Lance32497 December 11th, 2015 5:08 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 9030308)
I'm sorry for those terrible bugs. As I've said, the system is not yet complete and I've only fixed some of the existing bugs and I think its main purpose is to provide some information for other hackers. If the rest bugs can't be fixed recently, I will take a look at them in Feb approximately.

No it's fine, regarding to the catch one of 2v2 pokemon, well you're right, well I will still use it since those are just minors

kleenexfeu December 11th, 2015 11:35 AM

Quote:

Originally Posted by jiangzhengwenjzw (Post 9030308)
OK, I haven't taken a look at those "switch" points.

WADAFAK, I've never encountered with those bugs, sorry.

That's meant to imitate the Gen V feature, in which you can't throw a ball when there're 2 pokemon on the field. It also prevent many bugs from occurring.

I'm sorry for those terrible bugs. As I've said, the system is not yet complete and I've only fixed some of the existing bugs and I think its main purpose is to provide some information for other hackers. If the rest bugs can't be fixed recently, I will take a look at them in Feb approximately.

In vanilla game you can see the number of hp you have instead of the bar pressing start. So don't bother about this one

Lance32497 December 16th, 2015 3:32 AM

Here are the 2 routines that need to be checked becuse these are not working

Code:

  • Toggling Runaway
  • Special Shiny Pokemon box!

Well, these routines should be edited I think to work properly

Code:

  • Wild Pokemon Custom Moves
    •The reason why it needs to be edited because there are times that var 8000 is used in an event plus the wild battle thing, it automatically sets pokemon move whatever value is stored in that var. It would be good if it can be toggleabe by flag or var.
  • Get Pokèmon type
    •There should be a var that determines if the type you want to check is the 1st type and the 2nd type.



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.