The PokéCommunity Forums

The PokéCommunity Forums (https://www.pokecommunity.com/index.php)
-   Binary Hack Research & Development (https://www.pokecommunity.com/forumdisplay.php?f=195)
-   -   Code ASM Resource Thread (https://www.pokecommunity.com/showthread.php?t=339153)

Lunos July 27th, 2017 8:19 AM

Quote:

Originally Posted by Sakib66 (Post 9716640)
use TL's quick enhancer tool

The_Learner removed the DL Link until the next update because its modifications were messing some people's ROMs.

Quote:

Originally Posted by kleenexfeu (Post 8925169)
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

The routine has apparently some flaws.
They were fixed by @Squeetz in the community's Discord.
I don't know a single thing about ASM, but I thought someone needed to bring this up in case anyone wanted to use it.
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:
    ldr r0, party_player
    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
party_player:  .word 0x020244EC

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



ghoulslash July 27th, 2017 8:22 AM

Quote:

Originally Posted by Gameskiller01 (Post 9716626)
Sorry for being dumb, but how do I actually implement this into the game?

I would suggest learning how to compile and insert assembly instead of relying on tools.

1. First, you'll want to download HackMew's thumb compiler, found on this page.

2. Then, save the files you quoted individually as [filename].asm, eg. attack.asm. Using the windows command prompt, type 'thumb [filename].asm [filename].bin' in the same directory as your .asm file and the compiler. Then, open the .bin file with a hex editor, and insert into free space, making sure the offset ends in a 0,4,8, or C. With these particular routines, you'll need to also insert [00 01 0A 00] for red font and [00 07 0A 00] for blue font, somewhere in your rom, and then change the pointer at the bottom of each routine to the location of each 4bytes string. So, if you inserted 00 07 0A 00 at 0x123456, 0x08BBBBBB would become 0x08123456.

3. At the top of each assembly routine you're trying to insert, there is an insertion instruction that has been commented out, eg. @ 00 49 08 47 XX XX XX XX at x137134 in the attack.asm routine. This means, at offset 0x137134 you type the above hex, where XX XX XX XX is a reverse pointer (+1) to the location of the attack.bin hex you inserted into free space from step 2. For example, if you inserted attack.bin at 0x987654, for example, XX XX XX XX will be 55 76 98 08.

Do this for each routine and you should be all set!

I hope this helps. let me know if you have any issues.

Foxes July 29th, 2017 3:01 AM

Quote:

Originally Posted by ghoulslash (Post 9716685)
I would suggest learning how to compile and insert assembly instead of relying on tools.

1. First, you'll want to download HackMew's thumb compiler, found on this page.

2. Then, save the files you quoted individually as [filename].asm, eg. attack.asm. Using the windows command prompt, type 'thumb [filename].asm [filename].bin' in the same directory as your .asm file and the compiler. Then, open the .bin file with a hex editor, and insert into free space, making sure the offset ends in a 0,4,8, or C. With these particular routines, you'll need to also insert [00 01 0A 00] for red font and [00 07 0A 00] for blue font, somewhere in your rom, and then change the pointer at the bottom of each routine to the location of each 4bytes string. So, if you inserted 00 07 0A 00 at 0x123456, 0x08BBBBBB would become 0x08123456.

3. At the top of each assembly routine you're trying to insert, there is an insertion instruction that has been commented out, eg. @ 00 49 08 47 XX XX XX XX at x137134 in the attack.asm routine. This means, at offset 0x137134 you type the above hex, where XX XX XX XX is a reverse pointer (+1) to the location of the attack.bin hex you inserted into free space from step 2. For example, if you inserted attack.bin at 0x987654, for example, XX XX XX XX will be 55 76 98 08.

Do this for each routine and you should be all set!

I hope this helps. let me know if you have any issues.

Thank you! This kind of simple, easy to follow tutorial on how to insert ASM is exactly what I've been looking for! I'll try it now and see if it works.

EDIT: So when I try that, I get this error.
Quote:

attack.asm: Assembler messages:
attack.asm:0: Warning: end of file in comment; newline inserted
attack.asm:60: Error: junk at end of line, first unrecognized character is `R'
EDIT #2: nvm, I figured out that I had to insert the redfont and bluefont and change the .asm file to show where they are.

EDIT #3: So, if I put the hex for attack.bin at 0x71A6B0, XX XX XX XX would be B1 A6 71 08?

EDIT #4: It works! Thanks! Yours is the only tutorial for inserting ASM that I could actually follow and understand.

tkim July 29th, 2017 11:25 AM

Request for FR:

Volt Tackle by breeding with either parent holding a Light Ball.

Foxes July 30th, 2017 5:07 AM

Request for Platinum:

Having coloured stats based on natures. I don't know if this could be done by editing the ASM used to implement this into FireRed and changing the offsets or if they are just too different.

Either way, I think more work needs to be done on hacking 4th gen games, and I'd be happy to help (although I am very dumb). I'm currently looking into editing the hex of the 4th gen games but there doesn't seem to be any documentation on ASM for 4th gen and very little documentation on hex for 4th gen. If someone smarter than me can give me a good starting point as to where I could learn how to find out how to do this (if that makes any sense) I would be more than willing to learn.

Lunos July 30th, 2017 5:40 AM

Quote:

Originally Posted by esperance (Post 8865635)
This thread is for the development of new assembly routines and hacks based off of the requests of users. Feel free to make requests.

With that being said, would a Custom Wildbattle like this one, but that also allows you to choose the Battle Background be possible for FireRed?

ShyGuy25 August 1st, 2017 12:09 AM

Dumb question but what program is used to compile the ASM routines?

Foxes August 1st, 2017 1:46 AM

Quote:

Originally Posted by ShyGuy25 (Post 9719906)
Dumb question but what program is used to compile the ASM routines?

This easy to follow tutorial is what I used to be able to do it (with extremely little prior knowledge on the subject).

Quote:

Originally Posted by ghoulslash (Post 9716685)
I would suggest learning how to compile and insert assembly instead of relying on tools.

1. First, you'll want to download HackMew's thumb compiler, found on this page.

2. Then, save the files you quoted individually as [filename].asm, eg. attack.asm. Using the windows command prompt, type 'thumb [filename].asm [filename].bin' in the same directory as your .asm file and the compiler. Then, open the .bin file with a hex editor, and insert into free space, making sure the offset ends in a 0,4,8, or C. With these particular routines, you'll need to also insert [00 01 0A 00] for red font and [00 07 0A 00] for blue font, somewhere in your rom, and then change the pointer at the bottom of each routine to the location of each 4bytes string. So, if you inserted 00 07 0A 00 at 0x123456, 0x08BBBBBB would become 0x08123456.

3. At the top of each assembly routine you're trying to insert, there is an insertion instruction that has been commented out, eg. @ 00 49 08 47 XX XX XX XX at x137134 in the attack.asm routine. This means, at offset 0x137134 you type the above hex, where XX XX XX XX is a reverse pointer (+1) to the location of the attack.bin hex you inserted into free space from step 2. For example, if you inserted attack.bin at 0x987654, for example, XX XX XX XX will be 55 76 98 08.

Do this for each routine and you should be all set!

I hope this helps. let me know if you have any issues.

If you run into any problems, just look at the edits I made to my response to that message. It's probable that you may come across the same problems as I did.

Quote:

Originally Posted by Gameskiller01 (Post 9718002)
EDIT: So when I try that, I get this error.
Quote:

attack.asm: Assembler messages:
attack.asm:0: Warning: end of file in comment; newline inserted
attack.asm:60: Error: junk at end of line, first unrecognized character is `R'
EDIT #2: nvm, I figured out that I had to insert the redfont and bluefont and change the .asm file to show where they are.

EDIT #3: So, if I put the hex for attack.bin at 0x71A6B0, XX XX XX XX would be B1 A6 71 08?

EDIT #4: It works! Thanks! Yours is the only tutorial for inserting ASM that I could actually follow and understand.


tkim August 3rd, 2017 5:07 PM

1 Attachment(s)
[FR] Volt Tackle port from EM:

If you have free space from 0x270670-0x270741 (0xD2 bytes), use the IPS patch I provide here. ...It's a long story, so I will expand on this when I get the time. Fully working, I promise. You're gonna love it.

edit: A bit of explanation now: I took a look at an Emerald disassembly and found the routine that calls to check if the egg at the Day-Care is a pichu and if either of the parents are holding a Light Ball. I ported that exact routine into FR, but I had to make a copy of the routine at sub_80460D4 as to include the pichu check. Then I had to make special 0xB8 call the new routine instead of sub_80460D4. Since I had made a copy of the routine I also had to make sure the new routine used all the same offsets as before, and therefore I placed the routine at 0x270670, which I happened to have free space. I wanted to place the routine at something like 0x760000 or higher, but the old offsets wouldn't work any more. Down below are the uncompiled stuff:

This routine (located at 0x270670 in my patch) is a copy of the routine at 0x0460D4 but now includes the pichu egg check (in orange):
Code:

sub_80460D4:                @ CODE XREF: sp0B8_daycare+Cp

var_18        = -0x18
var_14        = -0x14

        PUSH    {R4-R6,LR}
        SUB    SP, SP,    #0x6C
        ADD    R5, R0,    #0
        ADD    R6, SP,    #0x7C+var_18
        ADD    R1, R6,    #0
        BL    sub_8046000
        ADD    R4, SP,    #0x7C+var_14
        STRH    R0, [R4]
        ADD    R0, R4,    #0
        ADD    R1, R5,    #0
        BL    incense_effects
        LDRH    R1, [R4]
        MOV    R0, SP
        ADD    R2, R5,    #0
        BL    sub_8046208
        MOV    R0, SP
        ADD    R1, R5,    #0
        BL    sub_8045AC0
        LDRB    R0, [R6,#1]
        MOV    R2, #0x8C @ '?'
        ADD    R1, R0,    #0
        MUL    R1, R2
        ADD    R1, R5,    R1
        LDRB    R0, [R6]
        MUL    R2, R0
        ADD    R2, R5,    R2
        MOV    R0, SP
        BL    daycare_build_child_moveset
        ldrh r0, [r4]
        cmp r0, #0xAC
        bne _08070918
        mov r0, sp
        add r1, r5, #0
        bl sub_82706FC
_08070918:

        MOV    R2, SP
        ADD    R2, #0x6A @ 'j'
        MOV    R0, #1
        STRB    R0, [R2]
        MOV    R0, SP
        MOV    R1, #0x2D @ '-'
        BL    pokemon_setattr
        LDR    R0, off_804614C
        MOV    R1, #0xFA @ '?'
        LSL    R1, R1,    #1
        ADD    R0, R0,    R1
        MOV    R1, SP
        MOV    R2, #0x64 @ 'd'
        BL    memcpy
        BL    party_compaction
        BL    party_count_pokemon
        ADD    R0, R5,    #0
        BL    sub_8045F70
        ADD    SP, SP,    #0x6C
        POP    {R4-R6}
        POP    {R0}
        BX    R0
@ End of function sub_80460D4

@ ---------------------------------------------------------------------------
.align 2
off_804614C:    .long 0x2024284        @ DATA XREF: sub_80460D4+52r


This routine (located at 0x2706FC in my patch) handles the volt tackle inheriting:
Code:

sub_80707A4:
    push {r4-r6,lr}
    add r5, r0, #0
    add r4, r1, #0
    add r0, r4, #0
    mov r1, #0xC
    bl pokemon_getattr_encrypted
    add r6, r0, #0
    add r4, #0x8C
    add r0, r4, #0
    mov r1, #0xC
    bl pokemon_getattr_encrypted
    cmp r6, #0xCA
    beq _080707C6
    cmp r0, #0xCA
    bne _080707E2

_080707C6:
    mov r4, #0xAC
    lsl r4, r4, #0x1
    add r0, r5, #0
    add r1, r4, #0
    bl pokemon_moveset_pad_
    lsl r0, r0, #0x10
    ldr r1, =(0xffff0000)
    cmp r0, r1
    bne _080707E2
    add r0, r5, #0
    add r1, r4, #0
    bl sub_803EB94

_080707E2:
    pop {r4-r6}
    pop {r0}
    bx r0


This last one makes sure the old offsets work correctly from the new offsets:
Code:

.text
.align 2
.thumb
.thumb_func

.org 0x0462B8
bl 0x270670

.org 0x27067A
bl 0x046000

.org 0x270686
bl 0x045FA0

.org 0x270690
bl 0x046208

.org 0x270698
bl 0x045AC0

.org 0x2706AE
bl 0x045CD0

.org 0x2706BC
bl 0x2706FC

.org 0x2706CC
bl 0x04037C

.org 0x2706DC
bl 0x1E5E78

.org 0x2706E0
bl 0x0937DC

.org 0x2706E4
bl 0x040C3C

.org 0x2706EA
bl 0x045F70

.org 0x270706
bl 0x03FD44

.org 0x270712
bl 0x03FD44

.org 0x270726
bl 0x03E89C

.org 0x270736
bl 0x03EB94


If anybody has a better way of porting this, please post it here.
edit2: I could probably just use bx r3?

tkim August 8th, 2017 1:46 PM

Quote:

Originally Posted by DizzyEgg (Post 9171350)
Pokemon Emerald Multichoice Scrolling Box

Spoiler:
So, the mechanic for that is already implemented, we just have to repoint some tables. So let's get down to work.
First, there's a table at 0x085B2CF0. Each entry is a pointer to text to be displayed in the box. One set consist of 16 options. This is important. Anyway, repoint to free space and change pointers to this table. It ends at 0x085B3030.

Now, there's a jumptable at 0x813A156. It ends at 0x0813A19C. It has 12 entries, repoint it to free space. Now for every new set of options you want to add, you have to add a routine like this:
Spoiler:

Code:

.text
.thumb
.thumb_func
.align 2

main:
    mov r0, #5
    strh r0, [r3, #8] @how many are displayed
    mov r0, #8
    strh r0, [r3, #0xA] @how many are in total
    mov r0, #1
    strh r0, [r3, #0xC] @X coordinate
    mov r0, #1
    strh r0, [r3, #0xE] @Y coordinate
    mov r0, #9
    strh r0, [r3, #0x10] @unkown
    mov r0, #0xA
    strh r0, [r3, #0x12] @box height, should be displayed * 2
    mov r0, #0
    strh r0, [r3, #0x14] @unkown
    strh r4, [r3, #0x26] @task id, don't change it
    pop {r4}
    pop {r0}
    bx r0




Note that you can change parameters in those routines. Play with them and see which ones look the best for you. Now, every routine like that above, goes at the end of the repointed jumptable. There are 12-in game sets, so you'll start with 13. Change the byte at 0x813A148 to the amount of all sets.

One more thing, even though the table of pointers to text can only hold 16 pointers, it doesn't mean you're limited to only that many options. You can go to 126 max, because 127 is treated as hitting B. How? Well, in the routine above set how many in total to the amount you want and ignore occupied slots. For example if you want your set to have 50 options, divide it by 16, so you get 3 and some remainder. That means this set occupies 4 places in the jumptable, like this:
XX XX XX 08 00 00 00 00 00 00 00 00 00 00 00 00 NEW SET GOES HERE

Using it in a script is easy, just do this:
setvar 0x8004 slot in the jumptable (starts at 13, since 12 are already occupied in-game)
special 0x1BE
waitstate
Result is stored in the 0x800D. First option chosen is 0, second is 1, and so on. Hitting B be is 0x7F.
compare 0x800D 0x0
if 0x1 goto @first_option
....
compare 0x800D 0x7F
if 0x1 goto @chose_cancel

I hope everything's understandable. :)

I'm having a bit of trouble getting this to work. First of all, isn't the jumptable at 0x813A168 and not 0x813A156? I can repoint 0x813A168, but not your given 0x813A156. Second, I can only get the default choices to work. Anything above 12 (0xC) won't work for me. As soon as special 0x1BE is called ingame with a value of 0xD or more, the game freezes without the list showing up at all.

Here's the steps I did in order:

- repointed the first table located at 0x5B2CF0 to 0xDE43E0 and changed two pointers.
- repointed the jumptable located at 0x13A168 (instead of 0x13A156 as I couldn't find the pointers for it) to 0xDE4760 and changed one pointer.
- compiled your routine and inserted at 0xDE4794 (which is right after the repointed jumptable)
- added new entry (6 pre-existing pointers) to 0xDE4720.
- changed the byte at 0x813A148 from 0xC to 0xD.

Froosty August 9th, 2017 3:37 AM

DIFFERENT PALS FOR THE MALE AND FEMALE BAG [FR]
Thanks to KDS for helping me fix the error. :)
Insert this code:
Spoiler:

/* at 108340 put 00 48 00 47 (insert loc of this routine +1) */

.text
.align 2
.thumb

main:
ldr r0, =(0x0300500C)
ldr r0, [r0]
ldrb r0, [r0, #0x8]
cmp r0, #0x0
bne female
ldr r0, male_pal
b pal_load_maybe

female:
ldr r0, female_pal
b pal_load_maybe

pal_load_maybe:
ldr r1, handling_something
bl call_via_r1
ldr r1, return_loc
bx r1

call_via_r1:
bx r1

.align 2
male_pal: .word 0x08XXXXXX
female_pal: .word 0x08YYYYYY
handling_something: .word 0x0800ec28|1
return_loc: .word 0x08108352|1

Code:

XXXXXX is the pointer to AA AA AA 08 64 00
YYYYYY is the pointer to BB BB BB 08 64 00

where,
AA AA AA 08 is pointer to compressed male bag pallete
BB BB BB 08 is pointer to compressed female bag pallete




example:
Spoiler:
I insreted compressed pals at 900000 and 900030 and the routine at 800000,
so have a look at my rom data.
https://i.imgur.com/pl3ee2A.png
NOTE: you dont need to leave spaces between bytes, I did that just to make it easier to understand

AkameTheBulbasaur August 9th, 2017 9:04 PM

Scaled Experience Formula

In Generation V, a new way of determining the Experience Points gained after Battle was introduced. Previously, the Experience Formula was a flat one, which did not change based on Level Differences between your Pokemon and the other one.

In Black & White, they used a Scaled Experience Formula, which would cause your Pokemon to gain more experience if their opponent was a higher Level, and less if their opponent was a lower one.

Today, I am sharing a way to have this sort of Scaled Experience Points in Fire Red or Emerald. I have included the download link to a folder which contains four items.

Folder: (Download)
  1. The Routine (For Fire Red)
  2. The Routine (For Emerald)
  3. Think0028's Experience All Patch
  4. An Instruction Manual

The Instruction Manual explains how the routine works and any extra information that is necessary to know (particularly if you would like to modify this routine for your specific hack).

Important:
Considering I first uploaded the first version of this routine a long time ago, you may have an older version of it. This version may be preferable to that one, and it is smaller than the previous version is. Therefore, one can simply insert it over the old version and not have to repoint anything.

Extra Information

This routine is compatible with Think0028's Experience All Patch. His original download link is unfortunately broken, hence why I put it in the download folder. If it was still active, I would have linked directly to it.

If you inserted the Disable Experience Gain With Flag routine, originally by FBI, then you may wish to remove it, as this routine implements it. I am not sure if there is a conflict due to this, but at the very least there is a redundant check if you have two routines which both check the same Flag. It is also possible that this routine bypasses that one entirely, in which case you would want to remove it to avoid wasting space.

Thanks and credits to FBI for that original routine, as without it I would likely not have been able to find the correct branching address for this routine.

As I have nowhere else to post this information, I will say here that to remove the 1.5x Experience Boost you get for defeating a Pokemon in a Trainer Battle (like they did in Generation VII), do the following:

Put 07 E0 at 0x21DD8 (FireRed) or 0x4A698 (Emerald)

Put 1C E0 at 0x21E00 (FireRed) or put 28 E0 at 0x4A6C0 (Emerald)

Lunos August 10th, 2017 12:18 PM

The two requests I ever made over here were in vain.. allow me to try another one instead.
How about a port of JPAN's Overworld Hacks to Emerald?
I'm looking for a way to basically change a character's Front sprite, Back sprite and OWs to another one until I revert things back to how it was manually with another command.

Hotice03 August 11th, 2017 7:36 PM

I need help making an eeveelution evolution happen i need it made so when an eevee faints in battle and then you feed it a rare candy while its fainted after battle it evolves into a ghost type eeveelution

AkameTheBulbasaur August 11th, 2017 10:31 PM

Quote:

Originally Posted by Hotice03 (Post 9729572)
I need help making an eeveelution evolution happen i need it made so when an eevee faints in battle and then you feed it a rare candy while its fainted after battle it evolves into a ghost type eeveelution

This is just off the top of my head, so I haven't tested this or anything, but it should give you a head start.

First here's a link to a tutorial on how to add new evolution methods.

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

Second, you need a way to check if a Pokémon in your party is fainted. You can check the current HP of a Pokémon using the RAM offsets I posted here.

ldr r1, .FirstPoke
mov r1, #0x39
bl Decrypt
cmp r0, #0x0
beq Evolve

.FirstPoke is the first RAM offset in the lists I posted under the "Yours" heading. Basically what this little snippet does is it checks the current HP of the first Pokémon in your party and compares it to zero. If it's zero, the Pokémon is fainted and you can then branch to the next thing. You can change the party slot it checks, but ideally you would want a way for the code to know which Pokemon you selected.

It might help to look through the evolution routines posted in the tutorial and see how they're structured.

That's all I can really do without doing testing first, but that will have to wait until later because it's 2:30 in the morning as I'm posting this. PM me later if you still need help.

Derlo August 22nd, 2017 1:08 PM

Hello, I would like to request a hook routine to be added to the original TM's routine.
The new routine would be activated when the TM's were used and deleted, so a new item would be created in the ITEN bag.
If possible, include checking if the bag is full. If yes, discard new item.
Thanks in advance.

Enn August 24th, 2017 5:38 AM

Quote:

Originally Posted by Derlo (Post 9737411)
Hello, I would like to request a hook routine to be added to the original TM's routine.
The new routine would be activated when the TM's were used and deleted, so a new item would be created in the ITEM bag.
If possible, include checking if the bag is full. If yes, discard new item.
Thanks in advance.

Hello,
I think reuable tms are already done, if thats what you need...

Lunos August 24th, 2017 5:57 AM

Quote:

Originally Posted by Nisarg (Post 9738370)
Hello,
I think reuable tms are already done, if thats what you need...

It looks like he wants an item to be created after a TM is used and naturally deleted.
He didn't mentioned if he wants the exact TM to be created yet again, so I'd say he's not looking for reusable TMs.

Derlo August 24th, 2017 1:16 PM

Quote:

Originally Posted by Nisarg (Post 9738370)
Hello,
I think reuable tms are already done, if thats what you need...

Quote:

Originally Posted by Lunos (Post 9738386)
It looks like he wants an item to be created after a TM is used and naturally deleted.
He didn't mentioned if he wants the exact TM to be created yet again, so I'd say he's not looking for reusable TMs.

In fact what I need is to maintain the original routine that deletes the TM after use and add the creation of an item along with the TM exclusion.
Example: After using any TM, it is deleted from TM CASE and creates a NUGGET in the player bag.
And if possible show the informed message where the new item will be in the bag.

Koople August 25th, 2017 6:24 AM

Fixing some major bugs/oversights with this routine seemed worthy of a new post so anyone who has implemented it can notice the changes:

Adding a Dodge Rate for Catching Wild Pokemon [FR]

This routine uses the wild pokemon's base speed stat to calculate a probability that it will dodge a thrown pokeball (nominally ~5-10%)

(credits to Urz, shanem7, and ghoulslash for bug finding, scripting, and testing!)

Important Routine Notes:
  • This routine does not affect Safari Balls
  • In its current form, the Master Ball skips all dodge rate checks (can be changed easily)
  • The hook address may have changed from previous routine versions. Make sure you are using the correct hook address!

Insertion Instructions:
  1. Insert custom 'dodging' message at 0xXXYYZZ. This is what will be displayed when the Pokemon dodges your thrown Poke Ball
  2. Insert the following custom battle script at 0x08XXXXXX (requires the setword command. Also add #command cmdF6 0xF6 to commands.bsh file)
    Quote:

    waitmessage 0x40
    setword 0x203C020 0x08XXYYZZ
    printstring 0x184
    waitmessage 0x40
    cmdF6
  3. Replace .Message: word 0x8XXXXXX in the assembly routine below with the offset you compiled this battle script in
  4. Compile and insert the routine in free space (0x08TTUUVV)
  5. Insert 00 48 00 47 (VV+1) UU TT 08 at 0802D508

The Routine:
Code:

.text
.align 2
.thumb
.thumb_func

Main:
        ldr r1, .BallThrown
        ldrb r0, [r1]
        cmp r0, #0x1          @master ball
        bne OtherBall
        ldr r0, =(0x03004F90)
        ldr r1, =(0x0802D688 +1)
        bx r1

OtherBall:
        ldr r6, .TargetBank
        ldrb r0, [r6]
        ldr r1, .SpecialStatus
        lsl r0, r0, #0x2
        add r2, r1, r0
        ldr r0, [r2]
        ldr r1, =(0x000400C0)        @fly/dig/bounce/dive status flags
        and r0, r1
        cmp r0, #0x0
        bne DodgeBall    @auto dodge if offscreen
        ldrb r0, [r2, #0x1]
        mov r1, #0x4
        and r0, r1
        cmp r0, #0x0
        bne NoDodge        @ingrain -> cant dodge
        ldrb r0, [r6]
        mov r1, #0x58
        mul r0, r1
        ldr r1, .BattleStruct
        add r5, r1, r0
        mov r0, #0x4C
        add r0, r5, r0
        ldrb r1, [r0, #0x7]
        mov r2, #0x1
        and r1, r2
        cmp r1, #0x0
        bne DodgeBall    @substitute on -> auto dodge
        ldrb r1, [r0, #0x3]
        cmp r1, #0x20
        beq NoDodge        @frozen = can't dodge
        mov r2, #0x7
        and r1, r2
        cmp r1, #0x0
        bne NoDodge        @target is asleep -> cant dodge

GetThreshold:
        ldrh r0, [r5]
        mov r1, #0x1C
        mul r0, r0, r1
        ldr r1, .BaseStats
        add r0, r0, r1
        ldrb r0, [r0, #0x3]                @r0 = wild pokemon base speed
        mov r1, #0xA                @number to divide base speed by (change if you want)
        bl div_func                        @r0 =  base speed / 10
        mov r1, #0xD                @r1 = 13 (lower limit ~5% - change if you want)
        add r1, r0, r1                @r1 = 13 + base_speed/10 = base threshold

CheckParalysis:
        mov r0, r5
        add r0, #0x4F
        ldrb r0, [r0]
        cmp r0, #0x40
        bne CheckWrap
        lsr r1, r1, #0x1        @if pokemon paralyzed, its dodge rate is halved

CheckWrap:
        mov r0, r5
        add r0, #0x51
        ldrb r0, [r0]
        mov r2, #0xE0
        and r0, r2
        cmp r0, #0x0
        beq CheckDodge
        lsr r2, r1, #0x2
        sub r1, r1, r2                @3/4 dodge rate if trapped by wrap effect

CheckDodge:
        mov r3, r1
        bl rand_func
        lsr r0, r0, #0x8
        cmp r0, r3
        bls DodgeBall        @if r0 <= threshold value, the pokemon dodges the ball

NoDodge:
        ldr r3, .BaseStats        @replaced routine from hook
        ldr r2, .BattleStruct
        ldrb r1, [r6]
        mov r0, #0x58
        ldr r5, =(0x0802D510 +1)        @return to original routine
        bx r5

div_func:
        ldr r2, .Divide
        bx r2

rand_func:
        ldr r2, .Rand
        bx r2

DodgeBall:
        mov r0, #0x0
        mov r1, #0x6                @change to mov r1, #0x5 for ball deflection instead of dodging animation
        ldr r2, =(0x0800E194 +1)
        bl linker
        ldr r5, =(0x02023BC4)
        ldrb r0, [r5]
        ldr r2, =(0x08017248 +1)
        bl linker
        ldr r1, =(0x02023D74)
        ldr r0, .DodgeMessage
        ldr r2, =(0x0802D7EC +1)

linker:
        bx r2

.align 2
.BallThrown:        .word 0x02023D68
.Rand: .word 0x08044EC9
.WildPoke:        .word 0x0202402C
.BaseStats: .word 0x08254784
.Divide:        .word 0x081E4019
.UserBank:        .word 0x02023D6B
.TargetBank:        .word 0x02023D6C
.BattleStruct:        .word 0x02023BE4
.SpecialStatus:        .word 0x02023DFC
.DodgeMessage:        .word 0x08XXXXXX        @battle script to display custom message


Current Routine Features:
  1. Target will automatically dodge a thrown ball if it is off-screen (dig, fly, bounce, dive) or has a substitute out
  2. Target will never dodge if it is asleep, frozen, or rooted in the ground (ingrain)
  3. 50% dodge rate for paralysis and 75% dodge rate if trapped by wrap effect
There are lots of other little dodge rate modifiers one could implement, such as speed/evasion stat modifiers, held item, ability, weather, etc. I have implemented some of these, so let me know if you want me to add these in!

Skeli August 31st, 2017 8:47 PM

Expanding the Bag Entirely [FR]

-Big Edit: The routines have been completely rewritten from scratch to work properly now.

This has been done in bits and pieces over the years (I believe it's actually been done completely for Emerald), so I decided to rewrite the bag storage routine for Fire Red.

Pre-Requisites
  • JPAN's Save Block Recycle
    Spoiler:
    Code:

    .thumb
    .global JPAN_Save_Block_Recycle
    .equ rom, 0x8000000
    .equ offset, 0xA00000 @YOUR INSERT OFFSET HERE

    .org 0xD991E, 0xFF
            bx r7

    .org 0xD995C, 0xFF
    .word Recycle_2 + rom + 1

    .org 0xD9EDC, 0xFF
            ldr r0, .Pointer1
            bx r0
    .align 2
    .Pointer1: .word Recycle_1 + rom + 1

    .org 0x3FEC9A, 0xFF
    .byte 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xE0, 0x1F, 0xF0, 0x0F, 0xD0, 0x2F, 0x98, 0xD, 0x0, 0x0, 0xF0, 0x0F, 0xF0, 0xF, 0xF0, 0xF, 0xE0, 0x1F, 0xF0, 0xF, 0xD0, 0x2F, 0xF0, 0xF, 0xC0, 0x3F, 0xF0, 0xF, 0xB0, 0x4F, 0xF0, 0xF, 0xA0, 0x5F, 0xF0, 0xF, 0x90, 0x6F, 0xF0, 0xF, 0x80, 0x7F, 0x50, 0x4

    .org offset, 0xFF
    Recycle_1:
            ldr r1, [r4]
            mov r3, #0xFF
            lsl r3, #0x4
            add r3, r1
            ldrh r0, [r3, #0x4]
            cmp r0, #0x0
            beq Size1
            cmp r0, #0x4
            beq Size2
            cmp r0, #0xD
            beq Size3

    BigLoop:
            cmp r5, #0xD
            ble Return
            mov r0, #0x1
            pop {r3}
            mov r8, r3
            pop {r4-r7,pc}

    Size1:
            mov r1, #0xCC
            ldr r2, .Loc1
            b SmallLoop

    Size2:
            mov r1, #0x96
            lsl r1, #0x2
            ldr r2, .Loc2
            b SmallLoop

    Size3:
            mov r1, #0xBA
            lsl r1, #0x4
            ldr r2, .Loc3

    SmallLoop:
            sub r3, #0x4
            ldr r0, [r3]
            str r0, [r2]
            sub r2, #0x4
            sub r1, #0x4
            cmp r1, #0x0
            bne SmallLoop
            b BigLoop

    .align 2
    .Loc1: .word 0x203C1C8
    .Loc2: .word 0x203C420
    .Loc3: .word 0x203CFC0

    Return:
            ldr r0, .Return
            bx r0

    .align 2
    .Return: .word 0x80D9E71
    .word 0xFFFFFFFF

    Recycle_2:
            mov r7, #0xFF
            lsl r7, #0x4
            add r7, r1, r7
            strh r0, [r7, #0x6]
            ldrh r6, [r7, #0x4]
            cmp r6, #0x0
            beq Size1_2
            cmp r6, #0x4
            beq Size2_2
            cmp r6, #0xD
            beq Size3_2
            lsl r0, #0x0

    Return_2:
            ldr r0, .Return2
            bx r0

    .align 2
    .Return2: .word 0x80D9923

    Size1_2:
            mov r3, #0xCC
            ldr r2, .Loc1_2
            b SmallLoop_2

    Size2_2:
            mov r3, #0x96
            lsl r3, #0x2
            ldr r2, .Loc2_2
            b SmallLoop_2

    Size3_2:
            mov r3, #0xBA
            lsl r3, #0x4
            ldr r2, .Loc3_2

    SmallLoop_2:
            sub r7, #0x4
            ldr r0, [r2]
            str r0, [r7]
            sub r2, #0x4
            sub r3, #0x4
            cmp r3, #0x0
            bne SmallLoop_2
            b Return_2

    .align 2
    .Loc1_2: .word 0x203C1C8
    .Loc2_2: .word 0x203C420
    .Loc3_2: .word 0x203CFC0


    Insertion Instructions:
    1. Change the .equ offset, 0xA00000 to the offset where you plan on inserting the routine.
    2. Compile the asm file.
    3. Open the .bin file and copy all the data from 0xD991E, 0xD995C, 0xD9EDC 0x3FEC9A, and your insert offset (your offset's data will go to the end of the bin file) to those same offsets in your rom.
  • An updated Conversion attack routine:
    Spoiler:

    In the following routine, change the location of your attack data at the top if necessary (if you haven't added new moves to your game it probably isn't). Assemble the routine, copy the data from the .bin file, and then do a paste-write at 0x28604 in your rom.

    Or if you don't understand ASM, copy and paste the compiled version to 0x28604 in your rom:
    Code:

    F0 B5 1B 4F 18 48 19 49 09 78 58 22 51 43 40 18 03 1C 44 7D 85 7D 00 88 12 49 0C 22 50 43 09 18 08 78 A0 42 10 D0 A8 42 0E D0 58 75 98 75 04 1C 10 48 FD 21 01 70 03 21 41 70 84 70 FF 21 C1 70 39 68 05 31 39 60 F0 BD 3A 68 51 78 90 78 00 02 01 43 D0 78 00 04 01 43 10 79 00 06 01 43 39 60 F0 BD C0 46 06 0C 25 08 F0 3B 02 02 6B 3D 02 02 74 3D 02 02 B8 2A 02 02


    (This compiled version assumes you haven't added any new moves)

    Routine:
    Code:

    .thumb
    .global atk90_changetypestoenemyattacktype

    .equ Attack_Data, 0x250C04 @0x900000 for Mr. DS
    .equ rom, 0x8000000

    @Conversion: Insert at 0x28604
    CheckMove:
            push {r4-r7, lr}
            ldr r7, .ScriptLoc
            ldr r0, .BattleData
            ldr r1, .UserBank
            ldrb r1, [r1]
            mov r2, #0x58
            mul r1, r2
            add r0, r1
            mov r3, r0
            ldrb r4, [r0, #0x15] @first type
            ldrb r5, [r0, #0x16] @second type
            ldrh r0, [r0] @First Move

    GetMoveType:
            ldr r1, .MoveData
            mov r2, #0xC
            mul r0, r2
            add r1, r0
            ldrb r0, [r1]

    CheckTypeMatch:
            cmp r0, r4
            beq Failed
            cmp r0, r5
            beq Failed

    Store:
            strb r0, [r3, #0x15]
            strb r0, [r3, #0x16]

    Return:
            mov r4, r0
            ldr r0, =0x2022AB8
            mov r1, #0xFD
            strb r1, [r0]
            mov r1, #0x3
            strb r1, [r0, #0x1]
            strb r4, [r0, #0x2]
            mov r1, #0xFF
            strb r1, [r0, #0x3]
            ldr r1, [r7]
            add r1, #0x5
            str r1, [r7]
            pop {r4-r7, pc}

    Failed:
            ldr r2, [r7]
            ldrb r1, [r2,#1]
            ldrb r0, [r2,#2]
            lsl r0, #8
            orr r1, r0
            ldrb r0, [r2,#3]
            lsl r0, #0x10
            orr r1, R0
            ldrb r0, [r2,#4]
            lsl r0, #0x18
            orr r1, r0
            str r1, [r7]
            pop {r4-r7, pc}

    .align 2
    .MoveData: .word Attack_Data + 0x2  + rom
    .BattleData: .word 0x2023BE4 + 0xC
    .UserBank: .word 0x2023D6B
    .ScriptLoc: .word 0x2023D74




    Why Conversion?
    Spoiler:
    Some of the space from the old Conversion routine is used for the bag expansion. To free up this space, Conversion was rewritten to match its Gen 6+ effect.

The Code
Spoiler:
Code:

.equ Total_Item_Amount, 700 @Change to largest item index number

.equ Regular_Item_Num, 200 @Change to number of items in main bag pocket divided by 2
.equ Key_Item_Num, 30 @Change to number of items in key item pocket divided by 2
.equ Poke_Ball_Num, 14 @Change to number of items in Poke Ball pocket divided by 2
.equ TM_Num, 128 @Change to number of TMs + HMs
.equ Berry_Num, 67 @Change to number of berries

@When changing the following RAM Adresses, make sure no data is being overwritten.
@For example, if you want to change the Poke_Ball_Ram, it needs to be changed to
@a location where there are (Poke_Ball_Num * 2 * 4) bytes of memory free.
.equ TM_Ram, 0x202583C @Change to your TM Case RAM address
.equ Berry_Ram, 0x2025A3C @Change to your Berry Pouch RAM address
.equ Key_Item_Ram, 0x203C7D0 @Change to your Key Item pocket RAM address
.equ Poke_Ball_Ram, 0x203C8C0 @Change to your main Poke Ball Pocket RAM address
.equ Item_Ram, 0x203C930 @Change to your main bag pocket RAM address

.equ Free_Ram, 0x203D900 @Don't change unless you don't like this free ram
.equ offset, 0x8D1980 @Change to Free Space Offset

.equ largest_pocket_size, Regular_Item_Num * 2
.equ largest_pocket_size_plus_one, largest_pocket_size + 1
.equ strings_size, largest_pocket_size_plus_one * 19

.equ rom, 0x8000000

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HelperRoutine

.org 0x28760, 0xFF
GetItemAmount:
        push {r1,lr}
        ldr r0, .CurrentPocket
        ldrb r0, [r0]
        lsl r0, #0x1
        ldr r1, .ItemStorage
        ldrh r0, [r0, r1]
        pop {r1,pc}

.align 2
.CurrentPocket: .word 0x203AD02
.ItemStorage: .word Free_Ram

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Decryption and DMA Negation
@The first few of these actually decrypt the Pokemon Data because why not?

.org 0x3F906, 0xFF
mov r8, r8
str r0, [r2]
ldr r1, [r3, #0x4]
mov r8, r8

.org 0x3F92A, 0xFF
mov r8, r8
str r0, [r2]
ldr r1, [r3]
mov r8, r8

.org 0x3F94C, 0xFF
mov r0, #0x0
mov r8, r8
mov r8, r8

.org 0x3FDA8, 0xFF
b 0x3FDC2

.org 0x40530, 0xFF
b 0x40550

.org 0x40AE6, 0xFF
mov r8, r8

.org 0x4C062, 0xFF
mov r1, #0x0
mov r1, #0x0

.org 0x4C13C, 0xFF
mov r4, #0x0

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

.org 0x6BDEC, 0xFF
        ldr r0, .BerryFix1Ptr
        bx r0
.align 2
.BerryFix1Ptr: .word BerryFix1Ptr + rom + 1

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Removal of Item Limiters

.org 0x98998, 0xFF
.word Total_Item_Amount

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Routines Related to Obtaining Items

.org 0x99DFC, 0xFF
ldrh r0, [r0, #0x4]

.org 0x99E1A, 0xFF
ldrh r4, [r4, #0x4]

.org 0x99E44, 0xFF
ldr r1, .BagPocket0

@Regular items
ldr r0, ram_FREE_item
str r0, [r1]
mov r0, #Regular_Item_Num
lsl r0, #0x1 @400 regular items
strh r0, [r1, #0x4]

@Key items
ldr r0, ram_FREE_keyitem
str r0, [r1, #0x8]
mov r0, #(Key_Item_Num * 2) @60 key items
strh r0, [r1, #0xC]

@Poke balls
ldr r0, ball_ram
str r0, [r1, #0x10]
mov r0, #(Poke_Ball_Num * 2) @28 balls
strh r0, [r1, #0x14]

@Tms
ldr r0, tm_ram
str r0, [r1, #0x18]
mov r0, #TM_Num @128 TMs
strh r0, [r1, #0x1C]

@Berries
ldr r0, berry_ram
str r0, [r1, #0x20]
add r1, #0x24
mov r0, #Berry_Num @67 berries
strh r0, [r1]
bx lr

.align 2
.BagPocket0:                .word 0x203988C
tm_ram:                        .word TM_Ram
berry_ram:                .word Berry_Ram
ram_FREE_keyitem:        .word Key_Item_Ram
ball_ram:                .word Poke_Ball_Ram
ram_FREE_item:                .word Item_Ram

.org 0x99ED8, 0xFF
ldrh r1, [r0, #0x4]

.org 0x99EEA, 0xFF
lsl r0, r2, #0x10
lsr r0, r0, #0x10

.org 0x99F16, 0xFF
ldrh r1, [r0, #0x4]

.org 0x99F32, 0xFF
lsl r0, r0, #0x10
lsl r2, r0, #0x10

.org 0x99F6E, 0xFF
ldrh r1, [r0, #0x4]

.org 0x99F9A, 0xFF
lsl r0, r0, #0x10
lsr r2, r0, #0x10
ldrh r0, [r3, #0x4]

.org 0x99FD4, 0xFF
CheckBerryInBagFix:
        ldr r4, .LastResult
        ldr r0, .CheckBerryBerryRam
        ldrh r0, [r0]
        cmp r0, #0x0
        beq NoBerriesInBag
        mov r0, #0x1
        strh r0, [r4]
        pop {r4,pc}

NoBerriesInBag:
        mov r0, #0x0
        strh r0, [r4]
        pop {r4,pc}

.align 2
.CheckBerryBerryRam: .word Berry_Ram
.LastResult: .word 0x020370D0

.org 0x9A02A, 0xFF
ldrh r1, [r0, #0x4]

.org 0x9A05E, 0xFF
lsl r0, r0, #0x10
lsr r2, r0, #0x10
ldrh r0, [r3, #0x4]

.org 0x9A06E, 0xFF
lsl r0, r0, #0x10
lsr r0, r0, #0x10

.org 0x9A0B6, 0xFF
ldrh r1, [r0, #0x4]

.org 0x9A0EA, 0xFF
lsl r0, r0, #0x10
lsr r2, r0, #0x10
ldrh r0, [r5, #0x4]

.org 0x9A110, 0xFF
lsl r0, r0, #0x10
lsr r1, r0, #0x10

.org 0x9A14C, 0xFF
lsl r0, r0, #0x10
lsr r1, r0, #0x10

.org 0x9A186, 0xFF
lsl r0, r0, #0x10
lsr r2, r0, #0x10

.org 0x9A204, 0xFF
ldrh r1, [r0, #0x4]

.org 0x9A24E, 0xFF
lsl r0, r0, #0x10
lsr r2, r0, #0x10
ldrh r0, [r6, #0x4]

.org 0x9A2E8, 0xFF
ldrh r1, [r1, #0x4]

.org 0x9A58E, 0xFF @Shifting Items Up
lsl r1, #0x10
lsr r1, #0x10

.org 0x09A8A4, 0xFF
        lsl r0, #0x10
        lsr r0, #0x10
        ldr r1, .ItemLimit
        cmp r1, r0
        bge Return
        mov r0, #0x0
Return:
        bx lr

.align 2
.ItemLimit: .word Total_Item_Amount

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Routines Related to the Pokedex

@The original ram provided above for the berries overrites a copy of the Pokedex data.
@Thus, when the Berry Pouch is sorted upon opening it, garbage data from this dex
@data is loaded. These routines prevent this copy from being read from or written to.

BerryPokedexDataFix:
.org 0x104B34, 0xFF
b 0x104B56

.org 0x104B78, 0xFF
b 0x104BB0

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Routines Related to Viewing Items in Bag

Bag_Allocate_Stuff: @Credits to azurile13
.org 0x1083F4, 0xFF
        push {r4,lr}
        ldr r4, .AllocationPointer
        ldr r0, .LargestSize
        lsl r0, #0x3
        bl 0x2B9C @malloc
        str r0, [r4]
        cmp r0, #0x0
        beq No
        ldr r0, .strings_size
        bl 0x2B9C @malloc
        str r0, [r4, #0x4]
        cmp r0, #0x0
        beq No
        mov r0, #0x1
        b End

No:
        mov r0, #0x0

End:
        pop {r4,pc}

.align 2
.LargestSize: .word largest_pocket_size_plus_one
.AllocationPointer: .word 0x0203AD18
.strings_size: .word strings_size

.org 0x108440, 0xFF
bl 0x28760 @GetItemAmount
b 0x10844A

.org 0x10847E, 0xFF @Shop is dis one
bl 0x28760 @GetItemAmount
b 0x108488

.org 0x1084C2, 0xFF
bl 0x28760 @GetItemAmount
b 0x1084CA

.org 0x1085D8, 0xFF
push {r1}
bl 0x28760 @GetItemAmount
pop {r1}
cmp r0, r5

.org 0x108698, 0xFF
ldr r5, .Thing
ldrh r1, [r5, #0x6]
push {r1}
bl 0x28760 @GetItemAmount
pop {r1}
.hword 0x0
cmp r0, r4

.org 0x10871C, 0xFF
.Thing: .word 0x203ACFC

.org 0x10881E, 0xFF
ldr r1, .Thing2
ldrh r1, [r1, #0x6]
push {r1}
bl 0x28760 @GetItemAmount
pop {r1}
.hword 0x0
cmp r2, r0

.org 0x108850, 0xFF
.Thing2: .word 0x203ACFC

.org 0x108894, 0xFF
push {r1}
bl 0x28760 @GetItemAmount
pop {r1}
add r1, #0xD

.org 0x108A1C, 0xFF @Up Cursor Bug 1
ldr r1, .OpenBagBugFix1Pointer
bx r1
.align 2
.OpenBagBugFix1Pointer: .word OpenBagBugFix1 + rom + 1

.org 0x108A40, 0xFF @Up Cursor Bug 2
ldr r0, .OpenBagBugFix2Pointer
bx r0
.align 2
.OpenBagBugFix2Pointer: .word OpenBagBugFix2 + rom + 1
.hword 0x0

.org 0x108AC0, 0xFF @Up Cursor Bug 3
ldr r0, .OpenBagBugFix3Pointer
bx r0
.align 2
.OpenBagBugFix3Pointer: .word OpenBagBugFix3 + rom + 1

.org 0x108DC8, 0xFF
ldr r1, .StoreItemPointer
bx r1
.align 2
.StoreItemPointer: .word StoreItem + rom + 1

ldr r0, .Bag_Pocket_0_2
add r4, r1, r0
ldr r0, [r4]
ldrh r1, [r4, #0x4]

.org 0x108DEA, 0xFF
ldrh r0, [r4, #0x4]

.org 0x108E0A, 0xFF
ldrh r0, [r4, #0x4]

.org 0x108E20, 0xFF
ldr r0, .GetSmallestItemAmountPointer
bx r0
.align 2
.GetSmallestItemAmountPointer: .word GetSmallestItemAmount + rom + 1

.org 0x108E3C, 0xFF
.Bag_Pocket_0_2: .word 0x203988C

.org 0x108E4C, 0xFF
pop {r4-r6,pc}

.org 0x108FB6, 0xFF
ldrh r5, [r5, #0x6]
push {r1}
bl 0x28760 @GetItemAmount
pop {r1}
.hword 0x0
cmp r1, r0

.org 0x10904A, 0xFF
        ldrh r1, [r5, #0x6]
        push {r1}
        bl 0x28760 @GetItemAmount
        pop {r1}
        .hword 0x0
        cmp r4, r0

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Poke Dude Stuff

.org 0x10ADDE, 0xFF
        ldr r0, .PokeDudeBackupRegularBagFixPtr
        bx r0
.align 2
.PokeDudeBackupRegularBagFixPtr: .word PokeDudeBackupRegularBagFix + rom + 1

.org 0x10AE78, 0xFF
        ldr r0, .PokeDudeBackupRegularBagClearPtr
        bx r0
.align 2
.PokeDudeBackupRegularBagClearPtr: .word PokeDudeBackupRegularBagClear + rom + 1

.org 0x10AEDA, 0xFF
        ldr r0, .PokeDudeBackupBagRestorePtr
        bx r0
.align 2
.PokeDudeBackupBagRestorePtr: .word PokeDudeBackupBagRestore + rom + 1

.org 0x132E76, 0xFF
        ldr r1, .PokeDudeBackupTMCasePtr
        bx r1
.align 2
.PokeDudeBackupTMCasePtr: .word PokeDudeBackupTMCase + rom + 1

.org 0x132EB0, 0xFF
        ldr r0, .PokeDudeClearTMCasePtr
        bx r0
.align 2
.PokeDudeClearTMCasePtr: .word PokeDudeClearTMCase + rom + 1

.org 0x13318C, 0xFF
        ldr r0, .PokeDudeRestoreTMCasePtr
        bx r0
.align 2
.PokeDudeRestoreTMCasePtr: .word PokeDudeRestoreTMCase + rom + 1

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Remove Help System

.org 0x13B8C2, 0xFF
b 0x13B900

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@More Berry Stuff

.org 0x13D1C4, 0xFF
        mov r0, #Berry_Num + 1
        lsl r0, #0x3

.org 0x13D33C, 0xFF
BerryNumFixesHook:
        ldr r0, .BerryNumFixesPtr
        bx r0
.align 2
.BerryNumFixesPtr: .word BerryNumFixes + rom + 1

BerryFix2Hook:
.org 0x14A490, 0xFF
        ldr r0, .BerryFix2Ptr
        bx r0
.align 2
.BerryFix2Ptr: .word BerryFix2 + rom + 1

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@New Routine

.org offset, 0xFF
StoreItem:
        push {r4-r6,lr}
        lsl r0, r0, #0x18
        lsr r5, r0, #0x18
        mov r4, #0x0

GetItemInBagCount:
        mov r6, #0x0
        lsl r0, r4, #0x3
        ldr r1, .Table
        add r0, r1
        ldrh r3, [r0, #0x4]
        lsl r3, #0x1
        ldr r0, [r0]
        mov r1, #0x0

Loop:
        cmp r1, r3
        beq StoreAmount
        ldrh r2, [r0]
        cmp r2, #0x0
        beq CheckNextItemJustInCase
        add r0, #0x4
        add r1, #0x1
        b Loop

CheckNextItemJustInCase:
        ldrh r2, [r0, #0x4]
        cmp r2, #0x0
        beq StoreAmount
        add r0, #0x4
        add r1, #0x1
        mov r6, #0x1
        b Loop       

StoreAmount:
        cmp r6, #0x0
        beq NotShopSkip
        sub r1, #0x1
NotShopSkip:
        ldr r0, .ItemStorage2
        lsl r2, r4, #0x1
        add r0, r2
        strh r1, [r0]
        add r4, #0x1
        cmp r4, #0x3
        beq ReturnToThing
        b GetItemInBagCount

ReturnToThing:
        lsl r1, r5, #0x3
        ldr r0, =0x8108DD1
        bx r0

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

GetSmallestItemAmount:
        push {r1}
        ldr r0, .ItemStorage2
        lsl r1, r5, #0x1
        add r0, r1
        pop {r1}
        ldrh r0, [r0]
        ldr r3, =0x8108E29
        bx r3

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

OpenBagBugFix1:
        push {r0}
        lsl r0, r4, #0x1
        ldr r1, .ItemStorage2
        add r1, r0
        ldrh r1, [r1]
        pop {r0}
        add r0, r1, #0x1
        cmp r2, r0
        ldr r0, =0x8108A26 | 1
        bx r0

OpenBagBugFix2:
        lsl r3, r4, #0x1
        ldr r0, .ItemStorage2
        add r0, r3
        ldrh r0, [r0]
        add r3, r0, #0x1
        ldr r4, =0x8108A4C | 1
        bx r4

OpenBagBugFix3:
        lsl r1, r6, #0x1
        ldr r0, .ItemStorage2
        add r0, r1
        ldrh r0, [r0]
        add r0, #0x1
        ldr r1, =0x8108AC8 | 1
        bx r1

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

PokeDudeBackupRegularBagFix:
        ldr r5, .PokeDudeItemBackupPtr
        ldr r0, .NewMallocPokeDudeBagSpace
        bl Calloc
        str r0, [r5]
        ldr r1, =Item_Ram
        ldr r2, =Regular_Item_Num * 2 * 4
        mov r4, r2
        bl Memcpy

        ldr r0, [r5]
        add r0, r4
        ldr r1, =Key_Item_Ram
        ldr r2, =Key_Item_Num * 2 * 4
        add r4, r2
        bl Memcpy

        ldr r0, [r5]
        add r0, r4
        ldr r1, =Poke_Ball_Ram
        ldr r2, =Poke_Ball_Num * 2 * 4
        bl Memcpy

        ldr r4, .SaveBlock1
        ldr r0, =0x810AE22 | 1
        bx r0

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

@0x810AE78 with r0
PokeDudeBackupRegularBagClear:
        ldr r0, =Item_Ram
        ldr r1, =Regular_Item_Num * 2
        bl RemoveNItems

        ldr r0, =Key_Item_Ram
        mov r1, #Key_Item_Num * 2
        bl RemoveNItems

        ldr r0, =Poke_Ball_Ram
        mov r1, #Poke_Ball_Num * 2
        bl RemoveNItems

        ldr r4, .SaveBlock1
        ldr r0, =0x810AEA4 | 1
        bx r0

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

@0x10AEDA with r0
PokeDudeBackupBagRestore:
        ldr r0, =Item_Ram
        ldr r1, [r5]
        ldr r2, =Regular_Item_Num * 2 * 4
        mov r4, r2
        bl Memcpy

        ldr r0, =Key_Item_Ram
        ldr r1, [r5]
        add r1, r4
        ldr r2, =Key_Item_Num * 2 * 4
        add r4, r2
        bl Memcpy

        ldr r0, =Poke_Ball_Ram
        ldr r1, [r5]
        add r1, r4
        ldr r2, =Poke_Ball_Num * 2 * 4
        bl Memcpy

        ldr r4, .SaveBlock1
        ldr r0, =0x810AF0C | 1
        bx r0

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

@0x8132E76 with r1
PokeDudeBackupTMCase:
        ldr r1, =TM_Ram
        ldr r2, =TM_Num * 4
        mov r5, r2
        bl Memcpy

        ldr r0, [r4]
        add r0, r5
        ldr r1, =Key_Item_Ram * 2 * 4
        ldr r2, =Key_Item_Num * 2 * 4
        bl Memcpy

        ldr r0, =0x8132E98 | 1
        bx r0

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

@0x132EB0 with r0
PokeDudeClearTMCase:
        ldr r0, =TM_Ram
        mov r1, #TM_Num
        bl RemoveNItems

        ldr r0, =Key_Item_Ram
        mov r1, #Key_Item_Num
        bl RemoveNItems

        ldr r0, =0x8132EC4 | 1
        bx r0

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

@0x813318C with r0
PokeDudeRestoreTMCase:
        ldr r0, =TM_Ram
        ldr r2, =TM_Num * 4
        bl Memcpy

        ldr r0, =Key_Item_Ram
        ldr r1, [r5]
        ldr r2, =Key_Item_Num * 2 * 4
        bl Memcpy

        ldr r0, =0x81331A4 | 1
        bx r0

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

BerryFix1Ptr:
        cmp r6, #0x1
        bls BerryFix1Return
        mov r0, r5
        bl GetItemPocket
        cmp r0, #0x5 @Berry Pouch
        bne BerryFix1Return
        ldr r0, =0x806BDFC | 1
        bx r0

BerryFix1Return:
        ldr r0, =0x806BE22 | 1
        bx r0

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

@0x14A490 with r0
BerryFix2:
        cmp r6, #0x0
        beq BerryFix2Return
        mov r0, r4
        bl GetItemMystery2 @BerryId

BerryFix2Return:
        ldr r0, =0x814A4C2 | 1
        bx r0

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

@0x13D33C with r0
BerryNumFixes:
        mov r0, r5
        bl GetItemMystery2
        mov r1, r0
        mov r0, r6
        mov r2, #0x2
        ldr r3, =0x813D344 | 1
        bx r3

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

Calloc:
        ldr r1, =0x8002BB0 | 1
        bx r1

Memcpy:
        ldr r3, =0x81E5E78 | 1
        bx r3

RemoveNItems:
        ldr r2, =0x809A274 | 1
        bx r2

GetItemPocket:
        ldr r1, =0x809A9D8 | 1
        bx r1

GetItemMystery2:
        ldr r1, =0x809A9B4 | 1
        bx r1

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

.align 2
.ItemStorage2: .word Free_Ram
.Table: .word TABLE + rom
.PokeDudeItemBackupPtr: .word 0x203AD2C
.NewMallocPokeDudeBagSpace: .word (Regular_Item_Num + Key_Item_Num + Poke_Ball_Num) * 2 * 4
.SaveBlock1: .word 0x3005008

.align 2
TABLE:
.word Item_Ram
.hword Regular_Item_Num, 0x0

.word Key_Item_Ram
.hword Key_Item_Num, 0x0

.word Poke_Ball_Ram
.hword Poke_Ball_Num, 0x0

.word 0xFFFFFFFF, 0xFFFFFFFF


The above code is written in such a way that if you were to insert it as is, you would have support for:
  • 400 Regular Items
  • 60 Key Items
  • 28 Poke Balls
  • 128 TMs/HMs
  • 67 Berries
Obviously if you don't need this many items, you're free to change the ram locations and item amounts by modifying the lines at the top of the routine. If you try to expand any of these values, make sure you change the ram locations if necessary.

Important Note About Berries: If you plan on adding new berries to your game, each berry needs to modified in G3T's item editor. Under Mystery1/2, change the value in the second box (Mystery 2) to the berry number for that berry. For instance, the Oran Berry is number 7. All berry numbers can be found on Bulbapedia.
If you don't plan on expanding berries, in the code, change Berry_Num to 43 and remove the bolded section labeled BerryNumFixesHook. Otherwise all your berries will be displayed with a berry number of 0 (or, alternatively, you could assign each berry a number like mentioned above).
If you do expand the berries, they will remain in a sorted order based on their item id. In my upcoming battle engine, a fix will be provided for this (mainly because I didn't want to write a decent sorting algorithm in Assembly).

Insertion Instructions:
  1. Customize to your liking
  2. Assemble the routine
  3. Copy the output bin file (so you should have a file called something like output.bin - Copy and fill this copy with FFs
  4. Create a patch using your blank (filled with FFs) file as the unmodified file, and the output file as the modified file
  5. Patch your rom

This has been confirmed to work with a vanilla Fire Red. However, I can't guarantee it will work with all roms in progress.


Credits

Enn September 5th, 2017 10:52 AM

Alright I'm making a request!
Everyone has probably heard about Bank system...
On which can allow the player to store his money, loans, interest (ofc in support with primes RTC) and other cool banking stuff.
PS this thread has helped me a lot thanks "A free helper" Blah ;) !

BluRose September 5th, 2017 7:59 PM

Quote:

Originally Posted by Nisarg (Post 9746312)
Alright I'm making a request!
Everyone has probably heard about Bank system...
On which can allow the player to store his money, loans, interest (ofc in support with primes RTC) and other cool banking stuff.
PS this thread has helped me a lot thanks "A free helper" Blah ;) !

read the op please &lt;3

Enn September 16th, 2017 6:35 AM

Aight, this request is similar to shinyquagsire's berry selection screen...
I need an asm which can show the party screen and on selecting the pokemon, exits and stores data in a var...
However theres a twist, im not talking about special 0x9f...
The mons need to be read from Ram where PSS stored the mons... So now y'all get it why its so complex...
If that is to be pulled off, it'd be amazing;)

BluRose September 17th, 2017 9:33 AM

Quote:

Originally Posted by Nisarg (Post 9754251)
Aight, this request is similar to shinyquagsire's berry selection screen...
I need an asm which can show the party screen and on selecting the pokemon, exits and stores data in a var...
However theres a twist, im not talking about special 0x9f...
The mons need to be read from Ram where PSS stored the mons... So now y'all get it why its so complex...
If that is to be pulled off, it'd be amazing;)

legit take the routine for special 0x9F
replace the part where it accesses your party with the new ram address. this likely just involves replacing an address from the routine, literally nothing more. callasm the new special and ezpz


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.