Thread: [Tutorial] Add animations in Fire Red
View Single Post
Old November 17th, 2009 (8:34 AM). Edited November 26th, 2009 by Juan.
Juan Juan is offline
Brazilian with a bad English
Join Date: Jun 2007
Location: Pindamonhangaba - SP
Age: 26
Nature: Adamant
Posts: 92
Documentation(Emerald): here
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
PS: LeafGreen uses the same structure then FireRed.
Explained by LU-HO.

Tileset 0:

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:

ROM:08070154 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
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: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)
ROM:08070164                 LDR     R1, =0x3000FB8
ROM:08070166                 LDR     R0, =0x8070121
ROM:08070168                 STR     R0, [R1]
Stores the offset of the routine in RAM

Now we see a secondary tileset that has animations.

Tileset 28(Vermilion GYM):

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:
ROM:0807031C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
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: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
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)

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:
@define AnimationRoutine = Animation Routine Offset + 1

	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:
ROM:08070120 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
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 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 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 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:080700A4 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
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:080700C8 dword_80700C8   DCD 0x83A7660           ; DATA XREF: FlowerAnimation+6r
ROM:080700CC dword_80700CC   DCD 0x6003F80           ; DATA XREF: FlowerAnimation+16r
ROM:080700D0 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
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:080700F0 dword_80700F0   DCD 0x83AA654           ; DATA XREF: WaterAnimation2+4r
ROM:080700F4 dword_80700F4   DCD 0x6003400           ; DATA XREF: WaterAnimation2+12r
ROM:080700F8 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
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: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:
ROM:080700BA                 LDR     R1, =0x6003F80  ; RAM Offset
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):
	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

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

More then 1 animation:
	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

	cmp r0, #1
	bne NoneAnimation
	bl Animation2

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


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.

- LU-HO (TilesetStructure)
- GBATEK (GBA especifications)
- Me ([Document]Tile Animations in Pokémon Emerald)
- Me² (this tutorial ^^)

OBS: Sorry for my bad english.
Attached Images
File Type: png flower1.PNG‎ (37.5 KB, 1377 views) (Save to Dropbox)
Reply With Quote