Tools, Tutorials & Resources Various tools to help you develop your hacks can be found here.

TrollandToad.com
Reply
 
Thread Tools
  #1    
Old January 28th, 2014 (5:11 AM).
Kyoko1 Kyoko1 is offline
Banned
     
    Join Date: Jan 2014
    Posts: 63
    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

    Relevant Advertising!

      #2    
    Old December 23rd, 2015 (1:34 AM). Edited December 23rd, 2015 by Bonnox.
    Bonnox Bonnox is offline
    Time (wasting) Lord
       
      Join Date: Sep 2015
      Location: Gallifrey, (IT)
      Age: 22
      Gender: Male
      Posts: 44
      wow, this is... just great! I was looking for something like this for months! I always tried to directly manipulate the 07 area just to see them being "obliterated" by the game engine! thank you. ^_^

      I'm sorry to clutter your good tutorial, but I have some questions.
      First I don't understand why you put the 0x08; and then, could I just calculate manually my OAM and slap it onto the LDR, thus skipping the data section?

      Finally, I haven't tried to do this yet, because I need something similar for AXVE. Maybe the procedures are the same, but the offsets change (almost certainly). So is there a tutorial somewhere about ruby? Or, maybe, what are your advices to help me investigate and "port" this amazing feature to the poor ruby ROM?

      really thankyou, and excuse me moderators if I revived a very old topic, but it is for the good of science this is really a worth one, so keep it alive!

      have a nice day

      EDIT:
      oh, no! you're banned! such a pity.
      is there anyone else who knows how to "prompt" me to do it for ruby?
      Reply With Quote
      Reply

      Quick Reply

      Join the conversation!

      Create an account to post a reply in this thread, participate in other discussions, and more!

      Create a PokéCommunity Account

      Sponsored Links
      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

      Forum Jump


      All times are GMT -8. The time now is 5:27 PM.