- 249
- Posts
- 12
- Years
- Seen Jun 17, 2024
Good evening to all.
Today I would like to explain how to implement the exp. sharing of sixth generation, whose peculiarity live in the fact that all the members of our team will receive experience, even if they haven't participated in the battle.
In this case, the pokémon in the field will receive half of the total amount of the experience they would normally receive without sharing experience, while to the others 1/6.
*NB: Before proceeding further, if you are not familiar with inserting asm routines, i suggest you to read some tutorial about it.
#1 - Tools needed
Before going into the insertion of the changes, it's necessary to define which tools we will need to arrive at the final result:
- HxD, available at the following link.
It will allow us to insert our compiled routines and make some hexadecimal changes necessary to "hook" our asm routines to the original code of the ROM.
- Compiler, available at the following link.
As you can imagine, we will need it to convert our ASM routines into a binary file "readable" from the ROM.
- XSE, available at the following link.
It will help us to insert the messages that will be displayed during the interaction with the exp.share in the bag.
- Item Editor, reperibile al seguente link.
It will help us to change some "attributes" of the exp.share item.
#2 - ASM routines and general explanations
In order to implement this feature, we use 4 asm routines.
The first routine allows us to define which pokemon of the team will receive the experience:
.THUMB
.ALIGN 2
PUSH {R0,R2-R7}
LDR R0, = 0x1200
BL CHECK_FLAG
CMP R0, #0
BEQ RETURN
MOV R4, #0
MOV R5, #0
LOOP:
LDR R0, = 0x03004360
MOV R1, #0x64
MUL R1, R4
ADD R0, R0, R1
MOV R1, #0x56
LDRH R2, [R0, R1]
CMP R2, #0
BEQ COUNTER
IS_EGG:
MOV R1, #0x2D
PUSH {R4,R5}
BL GET_DATA
POP {R4, R5}
CMP R0, #1
BEQ COUNTER
MOV R1, #1
LSL R1, R1, R4
ORR R5, R1
COUNTER:
ADD R4, #1
CMP R4, #6
BNE LOOP
MOV R1, R5
POP {R0,R2-R7}
LDR R0, = 0x08020030+1
BX R0
RETURN:
POP {R0,R2-R7}
LDR R2, = 0x02024DEA
MOV R1, #2
LDR R3, = 0x08020026+1
BX R3
CHECK_FLAG:
LDR R2, = 0x08069340+1
BX R2
GET_DATA:
LDR R2, = 0x0803CB60+1
BX R2
In this case, the only pokémon that will be excluded will be the KO ones and the eggs.
After compiling the routine in a free ROM offset, you need to make some changes with the HxD.
Go to 0x20024 and overwrite the bytes with 10 47
Go to 0x20058 and overwrite the bytes with XXXXXX08.
Instead of the XX, will be entered the offset of previous routine + 1 and in Little Endian format (example: 08123456 -> 57 34 12 08).
*NB: Both in this routine and in those to follow, the flag 1200 was used to discriminate if the exp.share is active/inactive.
You can change the flag value, as long as your choice is consistent and is reported in all routines.
For convenience, i highlighted the flag value used by the routines in red.
The second routine is used to define the amount of experience that pokémon in the field will receive:
.THUMB
.ALIGN 2
PUSH {R0-R7}
LDR R0, = 0x1200
BL CHECK_FLAG
CMP R0, #0
BEQ NOT_EXP
POP {R0-R7}
LSR R0, R1, #1
BACK_TO:
LDR R1, = 0x080201A8+1
BX R1
NOT_EXP:
POP {R0-R7}
LDR R2, = 0x080201E0+1
BX R2
CHECK_FLAG:
LDR R2, = 0x08069340+1
BX R2
In this case, the value of the total experience contained in R1, is divided by 2 and saved in R0 through the LSR instruction.
To "hook" the routine open the ROM with the Hex Editor, go to 0x2019A and overwrite the bytes with 000000480047XXXXXX08.
The speech made previously for the XX is also valid in this case.
The next routine is used to determine which Pokémon are in the field at that time and will therefore receive more experience:
.THUMB
.ALIGN 2
LDRH R0, [R3]
LDR R2, = 0x02016018
LDRB R2, [R2]
LDR R5, = 0x02024A6A
LDRB R7, [R5]
CMP R7, R2
BEQ RETURN
LDR R7, = 0x020239F8
LDRB R7, [R7]
MOV R3, #1
AND R7, R3
CMP R7, #1
BEQ DOUBLE
DIVIDE:
PUSH {R1-R7}
MOV R1, #3
BL DIVISION
POP {R1-R7}
RETURN:
STRH R0, [R1]
MOV R8, R1
LDR R0, = 0x08020376+1
BX R0
DOUBLE:
LDRB R7, [R5, #4]
CMP R7, R2
BEQ RETURN
B DIVIDE
DIVISION:
LDR R2, = 0x081E0868+1
BX R2
To "hook" the routine open the ROM with the Hex Editor, go to 0x20344 and overwrite the bytes with 00480047xxxxxx08.
The speech made previously for the XX is also valid in this case.
The last routine is used to define the new behavior of the exp.share, allowing us to display a message containing the current "state" of it (active/inactive):
.THUMB
.ALIGN 2
PUSH {LR}
PUSH {R0-R6}
LDR R0, .FLAG
BL CHECK_FLAG
MOV R7, R0
POP {R0-R6}
LSL R0, R0, #0x18
LSR R0, R0, #0x18
LDR R2, = 0x03004B20
LSL R1, R0, #2
ADD R1, R1, R0
LSL R1, R1, #3
ADD R1, R1, R2
LDRB R1, [R1,#0xC]
CMP R7, #0
BEQ ACTIVE
PUSH {R0-R7}
LDR R0, .FLAG
BL CLEAR_FLAG
POP {R0-R7}
LDR R2, = 0x08YYYYYY @MSG DE-ACTIVE
B WRITE_MSG
ACTIVE:
PUSH {R0-R7}
LDR R0, .FLAG
BL SET_FLAG
POP {R0-R7}
LDR R2, = 0x08XXXXXX @MSG ACTIVE
WRITE_MSG:
BL MSG
POP {R0}
BX R0
MSG:
PUSH {LR}
LSL R0, R0, #0x18
LSR R0, R0, #0x18
LSL R1, R1, #0x18
LSR R1, R1, #0x18
BL TEXTBOX
POP {R0}
BX R0
TEXTBOX:
PUSH {R0}
LDR R0, = 0x080C9098+1
B CALL
CHECK_FLAG:
PUSH {R0}
LDR R0, = 0x08069340+1
B CALL
SET_FLAG:
PUSH {R0}
LDR R0, = 0x080692F0+1
B CALL
CLEAR_FLAG:
PUSH {R0}
LDR R0, = 0x08069318+1
CALL:
MOV R10, R0
POP {R0}
BX R10
.ALIGN 2
.FLAG: .word 0x1200
Before compiling the routine, it's necessary to define the offsets of the two messages that will appear during the interaction with the item.
The first message will indicate that the function is active, otherwise the second will indicate that the function is deactivated.
To do this, we use the XSE tool.
To insert a message into the ROM, we use the following script:
Repeat the procedure described above also for the second message, this time replacing the YY.
After compiling the routine, insert it into the ROM and write down the offset.
#3 - From Normal item to Key Item
#4 - Final result
Today I would like to explain how to implement the exp. sharing of sixth generation, whose peculiarity live in the fact that all the members of our team will receive experience, even if they haven't participated in the battle.
In this case, the pokémon in the field will receive half of the total amount of the experience they would normally receive without sharing experience, while to the others 1/6.
*NB: Before proceeding further, if you are not familiar with inserting asm routines, i suggest you to read some tutorial about it.
#1 - Tools needed
Spoiler:
Before going into the insertion of the changes, it's necessary to define which tools we will need to arrive at the final result:
- HxD, available at the following link.
It will allow us to insert our compiled routines and make some hexadecimal changes necessary to "hook" our asm routines to the original code of the ROM.
- Compiler, available at the following link.
As you can imagine, we will need it to convert our ASM routines into a binary file "readable" from the ROM.
- XSE, available at the following link.
It will help us to insert the messages that will be displayed during the interaction with the exp.share in the bag.
- Item Editor, reperibile al seguente link.
It will help us to change some "attributes" of the exp.share item.
#2 - ASM routines and general explanations
Spoiler:
In order to implement this feature, we use 4 asm routines.
The first routine allows us to define which pokemon of the team will receive the experience:
Spoiler:
.THUMB
.ALIGN 2
PUSH {R0,R2-R7}
LDR R0, = 0x1200
BL CHECK_FLAG
CMP R0, #0
BEQ RETURN
MOV R4, #0
MOV R5, #0
LOOP:
LDR R0, = 0x03004360
MOV R1, #0x64
MUL R1, R4
ADD R0, R0, R1
MOV R1, #0x56
LDRH R2, [R0, R1]
CMP R2, #0
BEQ COUNTER
IS_EGG:
MOV R1, #0x2D
PUSH {R4,R5}
BL GET_DATA
POP {R4, R5}
CMP R0, #1
BEQ COUNTER
MOV R1, #1
LSL R1, R1, R4
ORR R5, R1
COUNTER:
ADD R4, #1
CMP R4, #6
BNE LOOP
MOV R1, R5
POP {R0,R2-R7}
LDR R0, = 0x08020030+1
BX R0
RETURN:
POP {R0,R2-R7}
LDR R2, = 0x02024DEA
MOV R1, #2
LDR R3, = 0x08020026+1
BX R3
CHECK_FLAG:
LDR R2, = 0x08069340+1
BX R2
GET_DATA:
LDR R2, = 0x0803CB60+1
BX R2
In this case, the only pokémon that will be excluded will be the KO ones and the eggs.
After compiling the routine in a free ROM offset, you need to make some changes with the HxD.
Go to 0x20024 and overwrite the bytes with 10 47
Go to 0x20058 and overwrite the bytes with XXXXXX08.
Instead of the XX, will be entered the offset of previous routine + 1 and in Little Endian format (example: 08123456 -> 57 34 12 08).
*NB: Both in this routine and in those to follow, the flag 1200 was used to discriminate if the exp.share is active/inactive.
You can change the flag value, as long as your choice is consistent and is reported in all routines.
For convenience, i highlighted the flag value used by the routines in red.
The second routine is used to define the amount of experience that pokémon in the field will receive:
Spoiler:
.THUMB
.ALIGN 2
PUSH {R0-R7}
LDR R0, = 0x1200
BL CHECK_FLAG
CMP R0, #0
BEQ NOT_EXP
POP {R0-R7}
LSR R0, R1, #1
BACK_TO:
LDR R1, = 0x080201A8+1
BX R1
NOT_EXP:
POP {R0-R7}
LDR R2, = 0x080201E0+1
BX R2
CHECK_FLAG:
LDR R2, = 0x08069340+1
BX R2
In this case, the value of the total experience contained in R1, is divided by 2 and saved in R0 through the LSR instruction.
To "hook" the routine open the ROM with the Hex Editor, go to 0x2019A and overwrite the bytes with 000000480047XXXXXX08.
The speech made previously for the XX is also valid in this case.
The next routine is used to determine which Pokémon are in the field at that time and will therefore receive more experience:
Spoiler:
.THUMB
.ALIGN 2
LDRH R0, [R3]
LDR R2, = 0x02016018
LDRB R2, [R2]
LDR R5, = 0x02024A6A
LDRB R7, [R5]
CMP R7, R2
BEQ RETURN
LDR R7, = 0x020239F8
LDRB R7, [R7]
MOV R3, #1
AND R7, R3
CMP R7, #1
BEQ DOUBLE
DIVIDE:
PUSH {R1-R7}
MOV R1, #3
BL DIVISION
POP {R1-R7}
RETURN:
STRH R0, [R1]
MOV R8, R1
LDR R0, = 0x08020376+1
BX R0
DOUBLE:
LDRB R7, [R5, #4]
CMP R7, R2
BEQ RETURN
B DIVIDE
DIVISION:
LDR R2, = 0x081E0868+1
BX R2
To "hook" the routine open the ROM with the Hex Editor, go to 0x20344 and overwrite the bytes with 00480047xxxxxx08.
The speech made previously for the XX is also valid in this case.
The last routine is used to define the new behavior of the exp.share, allowing us to display a message containing the current "state" of it (active/inactive):
Spoiler:
.THUMB
.ALIGN 2
PUSH {LR}
PUSH {R0-R6}
LDR R0, .FLAG
BL CHECK_FLAG
MOV R7, R0
POP {R0-R6}
LSL R0, R0, #0x18
LSR R0, R0, #0x18
LDR R2, = 0x03004B20
LSL R1, R0, #2
ADD R1, R1, R0
LSL R1, R1, #3
ADD R1, R1, R2
LDRB R1, [R1,#0xC]
CMP R7, #0
BEQ ACTIVE
PUSH {R0-R7}
LDR R0, .FLAG
BL CLEAR_FLAG
POP {R0-R7}
LDR R2, = 0x08YYYYYY @MSG DE-ACTIVE
B WRITE_MSG
ACTIVE:
PUSH {R0-R7}
LDR R0, .FLAG
BL SET_FLAG
POP {R0-R7}
LDR R2, = 0x08XXXXXX @MSG ACTIVE
WRITE_MSG:
BL MSG
POP {R0}
BX R0
MSG:
PUSH {LR}
LSL R0, R0, #0x18
LSR R0, R0, #0x18
LSL R1, R1, #0x18
LSR R1, R1, #0x18
BL TEXTBOX
POP {R0}
BX R0
TEXTBOX:
PUSH {R0}
LDR R0, = 0x080C9098+1
B CALL
CHECK_FLAG:
PUSH {R0}
LDR R0, = 0x08069340+1
B CALL
SET_FLAG:
PUSH {R0}
LDR R0, = 0x080692F0+1
B CALL
CLEAR_FLAG:
PUSH {R0}
LDR R0, = 0x08069318+1
CALL:
MOV R10, R0
POP {R0}
BX R10
.ALIGN 2
.FLAG: .word 0x1200
Before compiling the routine, it's necessary to define the offsets of the two messages that will appear during the interaction with the item.
The first message will indicate that the function is active, otherwise the second will indicate that the function is deactivated.
To do this, we use the XSE tool.
To insert a message into the ROM, we use the following script:
After clicking the button with the gears of the toolbar at the top, note the offset that will appear and replace it at XX in the asm routine.#dynamic 0x800000
#org @msg
= text message
Repeat the procedure described above also for the second message, this time replacing the YY.
After compiling the routine, insert it into the ROM and write down the offset.
#3 - From Normal item to Key Item
Spoiler:
The last remaining step before completing the implementation is to change some "attributes" of the exp.share.
To do this, use the Item Editor tool and open your ROM.
After selecting the "EXP. SHARE" item from the list of tools on the left, edit the following fields like this:
- Mystery Values with 1 and 1
- Field Usade Code Pointer with the offset of the last routine + 1.
To do this, use the Item Editor tool and open your ROM.
After selecting the "EXP. SHARE" item from the list of tools on the left, edit the following fields like this:
- Mystery Values with 1 and 1
- Field Usade Code Pointer with the offset of the last routine + 1.
#4 - Final result
Last edited: