Juan
Brazilian with a bad English
- 92
- Posts
- 17
- Years
- Age 34
- Pindamonhangaba - SP
- Seen Sep 21, 2016
Documentation(Emerald): here
PS: LeafGreen uses the same structure then FireRed.
Explained by LU-HO.
Tileset 0:
In this tutorial we will use only the "Animations routine pointer".
Decompile 0x8070154 (THUMB mode you should call the routines with "offset +1) we have:
What is important in this routine:
0x3000FB8 : Local in RAM where it is stored the pointer to the routine of animation.
0x8070121 : Offset of routine animation + 1 (THUMB)
Stores the offset of the routine in RAM
Now we see a secondary tileset that has animations.
Tileset 28(Vermilion GYM):
Decompile 0x807031C(807031D - 1) we have:
What is important in this routine:
0x3000FBC : Local in RAM where it is stored the pointer to the routine of secundary tileset animation.
0x8070305 : Offset of routine animation + 1 (THUMB)
Then:
0x3000FB8: Location for the pointer to the routine of the main tileset
0x3000FBC: Location for the pointer to the routine of the secundary tileset
Then, to add animations tilesets that do not have any, please enter the following routine:
Main Tileset:
Compile and enter the routine in an empty space in ROM.
Add a pointer to this routine + 1 in the header of the tileset you want.
But what comes to be 'AnimationRoutine'?
'AnimationRoutine' is the routine that will 'create' the animation.
Tileset 0 example:
Remember this:
Decompile 0x8070120:
To create our own animation routine, we have:
How to calculate the offset in RAM:
Flower Animation Example:
The RAM offset is 0x6003F80. But why?
It's simple.
See the image:
Offset in RAM is the exact place where the flower tile is stored.
Routine to add more animations (1 animation):
More then 1 animation:
I will not write the whole routine because there is a tutorial on ASM.
Each animation must contain:
r0 = Image Table pointer
r1 = RAM offset
r2 = size
And must call the subroutine 0x806FF04.
Image Table pointer:
Table of pointers to each frame.
Credits:
- LU-HO (TilesetStructure)
- GBATEK (GBA especifications)
- Me ([Document]Tile Animations in Pokémon Emerald)
- Me² (this tutorial ^^)
OBS: Sorry for my bad english.
Code:
struct FireRedTileset {
u8 compressed //00 = not compressed|| 01 = compressed
u8 tileset //00 = main tileset || 01 = secundary tileset
u16 filler //00 00
u32 *image //image pointer
u32 *palette //pallete pointer
u32 *block //block pointer
u32 *animation //Animations routine pointer
u32 *behavior //Behavior pointer
};
Explained by LU-HO.
Tileset 0:
Code:
0x2D4A94:
ROM:082D4A94 DCB 1 //Compressed
ROM:082D4A95 DCB 0 //main Tileset
ROM:082D4A96 DCW 0 //0x0
ROM:082D4A98 DCD off_8EA1D68 //Image pointer
ROM:082D4A9C DCD off_8EA1B68 //Pallete pointer
ROM:082D4AA0 DCD off_829F6C8 //Block pointer
ROM:082D4AA4 DCD off_8070155 //Animations routine pointer
ROM:082D4AA8 DCD off_82A1EC8 //Behavior pointer
In this tutorial we will use only the "Animations routine pointer".
Decompile 0x8070154 (THUMB mode you should call the routines with "offset +1) we have:
Code:
ROM:08070154
ROM:08070154 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:08070154
ROM:08070154
ROM:08070154 Tileset0AnimationHeader ; DATA XREF: ROM:082D4AA4o
ROM:08070154 LDR R1, =0x3000FAE
ROM:08070156 MOV R0, #0
ROM:08070158 STRH R0, [R1]
ROM:0807015A LDR R1, =0x3000FB0
ROM:0807015C MOV R2, 0xA0
ROM:0807015E LSL R2, R2, #2
ROM:08070160 ADD R0, R2, #0
ROM:08070162 STRH R0, [R1]
ROM:08070164 LDR R1, =0x3000FB8
ROM:08070166 LDR R0, =0x8070121
ROM:08070168 STR R0, [R1]
ROM:0807016A BX LR
ROM:0807016A ; End of function Tileset0AnimationHeader
ROM:0807016A
ROM:0807016A ; ---------------------------------------------------------------------------
ROM:0807016C dword_807016C DCD 0x3000FAE ; DATA XREF: Tileset0AnimationHeaderr
ROM:08070170 dword_8070170 DCD 0x3000FB0 ; DATA XREF: Tileset0AnimationHeader+6r
ROM:08070174 dword_8070174 DCD 0x3000FB8 ; DATA XREF: Tileset0AnimationHeader+10r
ROM:08070178 dword_8070178 DCD 0x8070121 ; DATA XREF: Tileset0AnimationHeader+12r
What is important in this routine:
0x3000FB8 : Local in RAM where it is stored the pointer to the routine of animation.
0x8070121 : Offset of routine animation + 1 (THUMB)
Code:
ROM:08070164 LDR R1, =0x3000FB8
ROM:08070166 LDR R0, =0x8070121
ROM:08070168 STR R0, [R1]
Now we see a secondary tileset that has animations.
Tileset 28(Vermilion GYM):
Code:
0x2D4A94:
ROM:082D4D34 DCB 1 //Compressed
ROM:082D4D35 DCB 1 //Secundary Tileset
ROM:082D4D36 DCW 0 //0x0
ROM:082D4D38 DCD off_82841F8 //Image pointer
ROM:082D4D3C DCD off_82849B8 //Pallete pointer
ROM:082D4D40 DCD off_82AB888 //Block pointer
ROM:082D4D44 DCD off_807031D //Animations routine pointer
ROM:082D4D48 DCD off_82ABD38 //Behavior pointer
Decompile 0x807031C(807031D - 1) we have:
Code:
ROM:0807031C
ROM:0807031C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:0807031C
ROM:0807031C
ROM:0807031C Tileset28AnimationHeader ; DATA XREF: ROM:082D4D44o
ROM:0807031C LDR R1, =0x3000FB2
ROM:0807031E MOV R0, #0
ROM:08070320 STRH R0, [R1]
ROM:08070322 LDR R1, =0x3000FB4
ROM:08070324 MOV R0, #0xF0
ROM:08070326 STRH R0, [R1]
ROM:08070328 LDR R1, =0x3000FBC
ROM:0807032A LDR R0, =0x8070305
ROM:0807032C STR R0, [R1]
ROM:0807032E BX LR
ROM:0807032E ; End of function Tileset28AnimationHeader
ROM:0807032E
ROM:0807032E ; ---------------------------------------------------------------------------
ROM:08070330 dword_8070330 DCD 0x3000FB2 ; DATA XREF: Tileset28AnimationHeaderr
ROM:08070334 dword_8070334 DCD 0x3000FB4 ; DATA XREF: Tileset28AnimationHeader+6r
ROM:08070338 dword_8070338 DCD 0x3000FBC ; DATA XREF: Tileset28AnimationHeader+Cr
ROM:0807033C dword_807033C DCD 0x8070305 ; DATA XREF: Tileset28AnimationHeader+Er
0x3000FBC : Local in RAM where it is stored the pointer to the routine of secundary tileset animation.
0x8070305 : Offset of routine animation + 1 (THUMB)
Then:
0x3000FB8: Location for the pointer to the routine of the main tileset
0x3000FBC: Location for the pointer to the routine of the secundary tileset
Then, to add animations tilesets that do not have any, please enter the following routine:
Main Tileset:
Code:
@define AnimationRoutine = Animation Routine Offset + 1
@thumb
thumb_code
main:
ldr r1,= #0x3000FAE
mov r0, #0
strh r0, [r1]
ldr r1,= #0x3000FB0
mov r2, #0xA0
lsl r2, r2, #2
add r0, r2, #0
strh r0, [r1]
ldr r1,= #0x3000FB8
ldr r0,= AnimationRoutine
str r0, [r1]
bx lr
Compile and enter the routine in an empty space in ROM.
Add a pointer to this routine + 1 in the header of the tileset you want.
But what comes to be 'AnimationRoutine'?
'AnimationRoutine' is the routine that will 'create' the animation.
Tileset 0 example:
Remember this:
0x8070121 : Offset of routine animation + 1 (THUMB)
Decompile 0x8070120:
Code:
ROM:08070120
ROM:08070120 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:08070120
ROM:08070120
ROM:08070120 Tileset0Main
ROM:08070120 PUSH {R4-R6,LR}
ROM:08070122 LSL R5, R0, #0x10
ROM:08070124 LSR R6, R5, #0x10
ROM:08070126 MOV R0, #7
ROM:08070128 AND R0, R6
ROM:0807012A CMP R0, #0
ROM:0807012C BNE loc_8070134
ROM:0807012E LSR R0, R5, #0x13
ROM:08070130 BL WaterAnimation
ROM:08070134
ROM:08070134 loc_8070134 ; CODE XREF: Tileset0Main+Cj
ROM:08070134 MOV R4, #0xF
ROM:08070136 AND R4, R6
ROM:08070138 CMP R4, #1
ROM:0807013A BNE loc_8070142
ROM:0807013C LSR R0, R5, #0x14
ROM:0807013E BL WaterAnimation2
ROM:08070142
ROM:08070142 loc_8070142 ; CODE XREF: Tileset0Main+1Aj
ROM:08070142 CMP R4, #2
ROM:08070144 BNE loc_807014C
ROM:08070146 LSR R0, R5, #0x14
ROM:08070148 BL FlowerAnimation
ROM:0807014C
ROM:0807014C loc_807014C ; CODE XREF: Tileset0Main+24j
ROM:0807014C POP {R4-R6}
ROM:0807014E POP {R0}
ROM:08070150 BX R0
ROM:08070150 ; End of function Tileset0Main
ROM:08070150
ROM:08070150 ; ---------------------------------------------------------------------------
@
ROM:080700A4
ROM:080700A4 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:080700A4
ROM:080700A4
ROM:080700A4 FlowerAnimation ; CODE XREF: Tileset0Main+28p
ROM:080700A4 PUSH {R4,LR}
ROM:080700A6 LSL R0, R0, #0x10
ROM:080700A8 LSR R0, R0, #0x10
ROM:080700AA LDR R4, =0x83A7660 ; Image Table pointer
ROM:080700AC MOV R1, #5
ROM:080700AE BL sub_81E4684
ROM:080700B2 LSL R0, R0, #0x10
ROM:080700B4 LSR R0, R0, #0xE
ROM:080700B6 ADD R0, R0, R4
ROM:080700B8 LDR R0, [R0]
ROM:080700BA LDR R1, =0x6003F80 ; RAM Offset
ROM:080700BC MOV R2, #0x80 ; Animation Size
ROM:080700BE BL sub_806FF04 ; Subroutine then save the data in the DMA3.
ROM:080700BE ; Don't change it.
ROM:080700C2 POP {R4}
ROM:080700C4 POP {R0}
ROM:080700C6 BX R0
ROM:080700C6 ; End of function FlowerAnimation
ROM:080700C6
ROM:080700C6 ; ---------------------------------------------------------------------------
ROM:080700C8 dword_80700C8 DCD 0x83A7660 ; DATA XREF: FlowerAnimation+6r
ROM:080700CC dword_80700CC DCD 0x6003F80 ; DATA XREF: FlowerAnimation+16r
ROM:080700D0
ROM:080700D0 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:080700D0
ROM:080700D0
ROM:080700D0 WaterAnimation2 ; CODE XREF: Tileset0Main+1Ep
ROM:080700D0 PUSH {LR}
ROM:080700D2 LSL R0, R0, #0x10
ROM:080700D4 LDR R2, =0x83AA654 ; Image Table pointer
ROM:080700D6 MOVL R1, 0x70000
ROM:080700DA AND R1, R0
ROM:080700DC LSR R1, R1, #0xE
ROM:080700DE ADD R1, R1, R2
ROM:080700E0 LDR R0, [R1]
ROM:080700E2 LDR R1, =0x6003400 ; RAM Offset
ROM:080700E4 MOVL R2, 0x600 ; Animation Size
ROM:080700E8 BL sub_806FF04 ; Subroutine then save the data in the DMA3.
ROM:080700E8 ; Don't change it.
ROM:080700EC POP {R0}
ROM:080700EE BX R0
ROM:080700EE ; End of function WaterAnimation2
ROM:080700EE
ROM:080700EE ; ---------------------------------------------------------------------------
ROM:080700F0 dword_80700F0 DCD 0x83AA654 ; DATA XREF: WaterAnimation2+4r
ROM:080700F4 dword_80700F4 DCD 0x6003400 ; DATA XREF: WaterAnimation2+12r
ROM:080700F8
ROM:080700F8 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:080700F8
ROM:080700F8
ROM:080700F8 WaterAnimation ; CODE XREF: Tileset0Main+10p
ROM:080700F8 PUSH {LR}
ROM:080700FA LSL R0, R0, #0x10
ROM:080700FC LDR R2, =0x83AB874 ; Image Table pointer
ROM:080700FE MOVL R1, 0x70000
ROM:08070102 AND R1, R0
ROM:08070104 LSR R1, R1, #0xE
ROM:08070106 ADD R1, R1, R2
ROM:08070108 LDR R0, [R1]
ROM:0807010A LDR R1, =0x6003A00 ; RAM Offset
ROM:0807010C MOVL R2, 0x240 ; Animation Size
ROM:08070110 BL sub_806FF04 ; Subroutine then save the data in the DMA3.
ROM:08070110 ; Don't change it.
ROM:08070114 POP {R0}
ROM:08070116 BX R0
ROM:08070116 ; End of function WaterAnimation
ROM:08070116
ROM:08070116 ; ---------------------------------------------------------------------------
ROM:08070118 dword_8070118 DCD 0x83AB874 ; DATA XREF: WaterAnimation+4r
ROM:0807011C dword_807011C DCD 0x6003A00 ; DATA XREF: WaterAnimation+12r
To create our own animation routine, we have:
- Animation offset (can be drawn on TileMolester)
- RAM offset *
How to calculate the offset in RAM:
Flower Animation Example:
Code:
ROM:080700BA LDR R1, =0x6003F80 ; RAM Offset
It's simple.
See the image:
Offset in RAM is the exact place where the flower tile is stored.
Routine to add more animations (1 animation):
Code:
@thumb
thumb_code
main:
push {r4-r6, lr}
lsl r5, r0, #0x10
lsr r6, r5, #0x10
mov r0, #7
and r0, r6
cmp r0, #0
bne NoAnimation
lsr r0, r5, #0x13
bl Animation
NoAnimation:
pop {r4-r6}
pop {r0}
bx r0
Animation:
...
More then 1 animation:
Code:
@thumb
thumb_code
main:
push {r4-r6, lr}
lsl r5, r0, #0x10
lsr r6, r5, #0x10
mov r0, #7
and r0, r6
cmp r0, #0
bne NoAnimation1
lsr r0, r5, #0x13
bl Animation
NoAnimation1:
cmp r0, #1
bne NoneAnimation
bl Animation2
NoneAnimation:
pop {r4-r6}
pop {r0}
bx r0
Animation1:
...
Animation2:
...
I will not write the whole routine because there is a tutorial on ASM.
Each animation must contain:
r0 = Image Table pointer
r1 = RAM offset
r2 = size
And must call the subroutine 0x806FF04.
Image Table pointer:
Table of pointers to each frame.
Credits:
- LU-HO (TilesetStructure)
- GBATEK (GBA especifications)
- Me ([Document]Tile Animations in Pokémon Emerald)
- Me² (this tutorial ^^)
OBS: Sorry for my bad english.
Last edited: