The PokéCommunity Forums  

Go Back   The PokéCommunity Forums > ROM Hacking > Tools, Tutorials & Resources
Sign Up Rules/FAQ Live Battle Blogs Mark Forums Read

Notices

Tools, Tutorials & Resources Various tools to help you develop your hacks can be found here.
New threads in this forum are to be approved by a moderator before they are displayed.


Advertise here

Reply
 
Thread Tools
  #1    
Old January 28th, 2014, 05:11 AM
Kyoko1
Banned
 
Join Date: Jan 2014
Send a message via Skype™ to Kyoko1

Advertise here
The object-system in FireRed

A few ASM hackers out there probably have wondered about it at least once: The objects in FireRed.
Some of you may also have tried to directly manipulate the OAM at 0x7000000 in the RAM, what didn't
work out.. The OAM updates every game-cycle and the bytes are refreshed by GameFreaks routines.
Because I needed to find out how this works (to make features like this..) I researched closely and with
the help of knizz' documentation about the OAM I finally found GFs routines and used it for myself.

I think I shouldn't write so much, I better tell you everything about my research now =)


Creating a new object

There are multiple routines of GF which all do something similar, but the most efficient function
I found is located at 0x08006F8C. It has 4 arguments in total, containing r0-r3.

Code:
.align 2
.thumb
.equ FUNCTION, 0x08006F8D

push {r0-r4, lr}
ldr r0, DATA
mov r1, #0xX    @ The X-position of the obj
mov r2, #0xY    @ The Y-position of the obj
mov r3,  #0x0    @ r3 must be set to 0 because the function needs it for calculation
ldr r4, =FUNCTION
bl execute
pop {r0-r4}
pop {pc}

execute:
bx r4
But what do we actually need at "ldr r0, DATA"?
Well, the data we need there is nothing else than the stuff at the oam-buffer at 0x0202063C.
It contains the oam-attributes 0, 1 and 2, which you can look up here and some callbacks.

Code:
.align 2

DATA: .word DATA2 + 0x08[The position of this ASM code]
DATA2:
.hword 0x2
.hword 0x1
.word OAM + 0x08[The position of this ASM code]
.word ANIM + 0x08[The position of this ASM code]
.word 0x0
.word 0x08231CFC
.word 0x080EE765
.byte 0xFF

.align 2

OAM:
.byte 0x0     @ This is meant to be the X-position but its overwritten ;)
.byte 0x0     @ This is the OBJ-shape (look GBAtek) 0 = square, 1 = horiz., 2 = vert., 3 = prohibited
.byte 0x0     @ This is meant to be the Y-position but its overwritten ;)
.byte 0xB0   @ This is the size of the obj (look GBAtek) C0 = 64x64, B0 = 32x32, 80 = 16x16, ..
.hword 0x1
.hword 0x0
     
.align 2

ANIM2:
.hword 0x21   @ TILENUMBER IN THE VRAM!! (from 0x06010000 are objects)
.hword 0xA
.byte 0xFE
.byte 0xFF
.hword 0x0
     
.align 2

ANIM:
.word ANIM2 + 0x08[The position of this ASM code]
You should focus on the things, which I wrote commands to. The other things are the same for every obj.
However, all of these created obj use the obj-pal #0x15 (0x050003E0).
In the next chapter you will learn how to change this obj-pal to #0x14 for example.


Changing the used pal & other useful stuff

You should change the pal, if you want, directly after you called the function.
And then you run yet into another problem: the OAM-buffer contains dozens of indexes, but which one
is actually our newly created object? Well, every "index" is 0x44 bytes long. And our useful function
which is at 0x08006F8C returns the index of our new object in r0!!
So you simply multiply r0 with 0x44 and add it to our OAM buffer, 0x0202063C!

Your code should look like this now:

Spoiler:
Code:
.align 2
.thumb
.equ FUNCTION, 0x08006F8D
.equ BUFFER, 0x0202063C

push {r0-r4, lr}
ldr r0, DATA
mov r1, #0xX    @ The X-position of the obj
mov r2, #0xY    @ The Y-position of the obj
mov r3,  #0x0    @ r3 must be set to 0 because the function needs it for calculation
ldr r4, =FUNCTION
bl execute
mov r1, #0x44
ldr r2, =BUFFER
mul r0, r0, r1   @mul index with 0x44
add r2, r2, r0   @add the (index*0x44) to buffer
pop {r0-r4}
pop {pc}

execute:
bx r4

.align 2

DATA: .word DATA2 + 0x08[The position of this ASM code]
DATA2:
.hword 0x2
.hword 0x1
.word OAM + 0x08[The position of this ASM code]
.word ANIM + 0x08[The position of this ASM code]
.word 0x0
.word 0x08231CFC
.word 0x080EE765
.byte 0xFF

.align 2

OAM:
.byte 0x0     @ This is meant to be the X-position but its overwritten ;)
.byte 0x0     @ This is the OBJ-shape (look GBAtek) 0 = square, 1 = horiz., 2 = vert., 3 = prohibited
.byte 0x0     @ This is meant to be the Y-position but its overwritten ;)
.byte 0xB0   @ This is the size of the obj (look GBAtek) C0 = 64x64, B0 = 32x32, 80 = 16x16, ..
.hword 0x1
.hword 0x0
    
.align 2

ANIM2:
.hword 0x21   @ TILENUMBER IN THE VRAM!! (from 0x06010000 are objects)
.hword 0xA
.byte 0xFE
.byte 0xFF
.hword 0x0
    
.align 2

ANIM:
.word ANIM2 + 0x08[The position of this ASM code]


Let's grab some information at gbatek.

Quote:
OBJ Attribute 2 (R/W)
Bit Expl.
0-9 Character Name (0-1023=Tile Number)
10-11 Priority relative to BG (0-3; 0=Highest)
12-15 Palette Number (0-15) (Not used in 256 color/1 palette mode)
Bit 10-11 you can just let them be 0, so just concentrate on Palette number.
You don't even need to bitcalculate there, write for example 0xE for palette 14.
But of course we need to add 0x5 to our current offset, cause we are still at attribute 0 =)

Spoiler:
Code:
.align 2
.thumb
.equ FUNCTION, 0x08006F8D
.equ BUFFER, 0x0202063C

push {r0-r4, lr}
ldr r0, DATA
mov r1, #0xX    @ The X-position of the obj
mov r2, #0xY    @ The Y-position of the obj
mov r3,  #0x0    @ r3 must be set to 0 because the function needs it for calculation
ldr r4, =FUNCTION
bl execute
mov r1, #0x44
ldr r2, =BUFFER
mul r0, r0, r1   @ mul index with 0x44
add r2, r2, r0   @ add the (index*0x44) to buffer
add r2, r2, #0x5
mov r1, #0xE     @ pal 14 :)
strb r1, [r2]
pop {r0-r4}
pop {pc}

execute:
bx r4

.align 2

DATA: .word DATA2 + 0x08[The position of this ASM code]
DATA2:
.hword 0x2
.hword 0x1
.word OAM + 0x08[The position of this ASM code]
.word ANIM + 0x08[The position of this ASM code]
.word 0x0
.word 0x08231CFC
.word 0x080EE765
.byte 0xFF

.align 2

OAM:
.byte 0x0     @ This is meant to be the X-position but its overwritten ;)
.byte 0x0     @ This is the OBJ-shape (look GBAtek) 0 = square, 1 = horiz., 2 = vert., 3 = prohibited
.byte 0x0     @ This is meant to be the Y-position but its overwritten ;)
.byte 0xB0   @ This is the size of the obj (look GBAtek) C0 = 64x64, B0 = 32x32, 80 = 16x16, ..
.hword 0x1
.hword 0x0
    
.align 2

ANIM2:
.hword 0x21   @ TILENUMBER IN THE VRAM!! (from 0x06010000 are objects)
.hword 0xA
.byte 0xFE
.byte 0xFF
.hword 0x0
    
.align 2

ANIM:
.word ANIM2 + 0x08[The position of this ASM code]


And that's basically how you create an obj and edit it afterwards!
Hmm, and how to delete an object? =(


Deleting an object

As you might've expected, gamefreak provides another function for us.
Its located at 0x08007280.
It only needs one arguement, the offset of our index in the OAM-buffer.
We can just use the calculation above to get this offset.
If you were clever enough to save the index, which stood in r0 after the function, to a free-space
in the RAM, you can load this byte from the offset and delete objects whenever you want.

Here's a little snippet:

Code:
.align 2
.thumb

.equ BUFFER, 0x0202063C
.equ FUNCTION, 0x08007281

push {r0-r4, lr}
mov r0, #0x0  @this is a placeholder for your own index-loading-from-freespace
mov r1, #0x44
ldr r2, =BUFFER
mul r0, r0, r1
add r0, r2, r0  @In r0 is now our offset
ldr r4, =FUNCTION
bl execute
pop {r0-r4}
pop {pc}

execute:
bx r4
Well, that was all my knowledge to the OAM, I still can't figure out how to interrupt gamefreaks function
to move and manipulate objects WHENEVER I WANT. Maybe i have to just put a different function in the
OAM-buffer, I don't know...

If you use any of this knowledge, it would be nice to mention knizz and me.

Have fun experimenting with this! =)
Reply With Quote
Reply
Quick Reply

Sponsored Links


Advertise here
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Minimum Characters Per Post: 25



All times are UTC -8. The time now is 02:52 PM.


Style by Nymphadora, artwork by Sa-Dui.
Like our Facebook Page Follow us on Twitter © 2002 - 2014 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 - 2014 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.